2018-08-21 22:26:59 +01:00
|
|
|
import os
|
|
|
|
import socket
|
|
|
|
|
|
|
|
from lxml import etree
|
|
|
|
|
2019-10-12 00:36:57 +01:00
|
|
|
from core import utils
|
|
|
|
from core.constants import IP_BIN
|
2019-09-28 06:31:56 +01:00
|
|
|
from core.emane.nodes import EmaneNet
|
2019-09-26 21:00:12 +01:00
|
|
|
from core.nodes import ipaddress
|
2019-09-10 22:20:51 +01:00
|
|
|
from core.nodes.base import CoreNodeBase
|
2018-08-21 22:26:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
def add_type(parent_element, name):
|
|
|
|
type_element = etree.SubElement(parent_element, "type")
|
|
|
|
type_element.text = name
|
|
|
|
|
|
|
|
|
2018-08-28 18:24:56 +01:00
|
|
|
def add_address(parent_element, address_type, address, interface_name=None):
|
|
|
|
address_element = etree.SubElement(parent_element, "address", type=address_type)
|
2018-08-21 22:26:59 +01:00
|
|
|
address_element.text = address
|
|
|
|
if interface_name is not None:
|
|
|
|
address_element.set("iface", interface_name)
|
|
|
|
|
|
|
|
|
|
|
|
def add_mapping(parent_element, maptype, mapref):
|
|
|
|
etree.SubElement(parent_element, "mapping", type=maptype, ref=mapref)
|
|
|
|
|
|
|
|
|
|
|
|
def add_emane_interface(host_element, netif, platform_name="p1", transport_name="t1"):
|
|
|
|
nem_id = netif.net.nemidmap[netif]
|
|
|
|
host_id = host_element.get("id")
|
|
|
|
|
|
|
|
# platform data
|
2019-10-18 18:33:31 +01:00
|
|
|
platform_id = f"{host_id}/{platform_name}"
|
2019-09-10 23:10:24 +01:00
|
|
|
platform_element = etree.SubElement(
|
|
|
|
host_element, "emanePlatform", id=platform_id, name=platform_name
|
|
|
|
)
|
2018-08-21 22:26:59 +01:00
|
|
|
|
|
|
|
# transport data
|
2019-10-18 18:33:31 +01:00
|
|
|
transport_id = f"{host_id}/{transport_name}"
|
2019-09-10 23:10:24 +01:00
|
|
|
etree.SubElement(
|
|
|
|
platform_element, "transport", id=transport_id, name=transport_name
|
|
|
|
)
|
2018-08-21 22:26:59 +01:00
|
|
|
|
|
|
|
# nem data
|
2019-10-18 18:33:31 +01:00
|
|
|
nem_name = f"nem{nem_id}"
|
|
|
|
nem_element_id = f"{host_id}/{nem_name}"
|
2019-09-10 23:10:24 +01:00
|
|
|
nem_element = etree.SubElement(
|
|
|
|
platform_element, "nem", id=nem_element_id, name=nem_name
|
|
|
|
)
|
2018-08-21 22:26:59 +01:00
|
|
|
nem_id_element = etree.SubElement(nem_element, "parameter", name="nemid")
|
|
|
|
nem_id_element.text = str(nem_id)
|
2018-08-28 18:24:56 +01:00
|
|
|
|
|
|
|
return platform_element
|
2018-08-21 22:26:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
def get_address_type(address):
|
2018-10-12 01:26:34 +01:00
|
|
|
addr, _slash, _prefixlen = address.partition("/")
|
2018-08-21 22:26:59 +01:00
|
|
|
if ipaddress.is_ipv4_address(addr):
|
|
|
|
address_type = "IPv4"
|
|
|
|
elif ipaddress.is_ipv6_address(addr):
|
|
|
|
address_type = "IPv6"
|
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
|
|
|
return address_type
|
|
|
|
|
|
|
|
|
|
|
|
def get_ipv4_addresses(hostname):
|
|
|
|
if hostname == "localhost":
|
|
|
|
addresses = []
|
2019-10-18 18:33:31 +01:00
|
|
|
args = f"{IP_BIN} -o -f inet address show"
|
2019-10-21 18:32:42 +01:00
|
|
|
output = utils.cmd(args)
|
2018-08-21 22:26:59 +01:00
|
|
|
for line in output.split(os.linesep):
|
|
|
|
split = line.split()
|
|
|
|
if not split:
|
|
|
|
continue
|
|
|
|
interface_name = split[1]
|
|
|
|
address = split[3]
|
|
|
|
if not address.startswith("127."):
|
|
|
|
addresses.append((interface_name, address))
|
|
|
|
return addresses
|
|
|
|
else:
|
|
|
|
# TODO: handle other hosts
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
|
|
class CoreXmlDeployment(object):
|
|
|
|
def __init__(self, session, scenario):
|
|
|
|
self.session = session
|
|
|
|
self.scenario = scenario
|
2019-09-10 23:10:24 +01:00
|
|
|
self.root = etree.SubElement(
|
|
|
|
scenario, "container", id="TestBed", name="TestBed"
|
|
|
|
)
|
2018-08-21 22:26:59 +01:00
|
|
|
self.add_deployment()
|
|
|
|
|
|
|
|
def find_device(self, name):
|
2019-10-18 18:33:31 +01:00
|
|
|
device = self.scenario.find(f"devices/device[@name='{name}']")
|
2018-08-21 22:26:59 +01:00
|
|
|
return device
|
|
|
|
|
|
|
|
def find_interface(self, device, name):
|
2019-09-10 23:10:24 +01:00
|
|
|
interface = self.scenario.find(
|
2019-10-18 18:33:31 +01:00
|
|
|
f"devices/device[@name='{device.name}']/interfaces/interface[@name='{name}']"
|
2019-09-10 23:10:24 +01:00
|
|
|
)
|
2018-08-21 22:26:59 +01:00
|
|
|
return interface
|
|
|
|
|
|
|
|
def add_deployment(self):
|
|
|
|
physical_host = self.add_physical_host(socket.gethostname())
|
|
|
|
|
2019-05-06 05:23:43 +01:00
|
|
|
for node_id in self.session.nodes:
|
|
|
|
node = self.session.nodes[node_id]
|
2019-04-30 07:31:47 +01:00
|
|
|
if isinstance(node, CoreNodeBase):
|
2018-08-21 22:26:59 +01:00
|
|
|
self.add_virtual_host(physical_host, node)
|
|
|
|
|
|
|
|
def add_physical_host(self, name):
|
|
|
|
# add host
|
2019-10-18 18:33:31 +01:00
|
|
|
root_id = self.root.get("id")
|
|
|
|
host_id = f"{root_id}/{name}"
|
2018-08-21 22:26:59 +01:00
|
|
|
host_element = etree.SubElement(self.root, "testHost", id=host_id, name=name)
|
|
|
|
|
|
|
|
# add type element
|
|
|
|
add_type(host_element, "physical")
|
|
|
|
|
|
|
|
# add ipv4 addresses
|
|
|
|
for interface_name, address in get_ipv4_addresses("localhost"):
|
|
|
|
add_address(host_element, "IPv4", address, interface_name)
|
|
|
|
|
|
|
|
return host_element
|
|
|
|
|
|
|
|
def add_virtual_host(self, physical_host, node):
|
2019-04-30 07:31:47 +01:00
|
|
|
if not isinstance(node, CoreNodeBase):
|
2019-10-18 18:33:31 +01:00
|
|
|
raise TypeError(f"invalid node type: {node}")
|
2018-08-21 22:26:59 +01:00
|
|
|
|
|
|
|
# create virtual host element
|
2019-10-18 18:33:31 +01:00
|
|
|
phys_id = physical_host.get("id")
|
|
|
|
host_id = f"{phys_id}/{node.name}"
|
2019-09-10 23:10:24 +01:00
|
|
|
host_element = etree.SubElement(
|
|
|
|
physical_host, "testHost", id=host_id, name=node.name
|
|
|
|
)
|
2018-08-21 22:26:59 +01:00
|
|
|
|
|
|
|
# add host type
|
|
|
|
add_type(host_element, "virtual")
|
|
|
|
|
|
|
|
for netif in node.netifs():
|
2018-08-28 18:24:56 +01:00
|
|
|
emane_element = None
|
2019-09-28 06:31:56 +01:00
|
|
|
if isinstance(netif.net, EmaneNet):
|
2018-08-28 18:24:56 +01:00
|
|
|
emane_element = add_emane_interface(host_element, netif)
|
|
|
|
|
|
|
|
parent_element = host_element
|
|
|
|
if emane_element is not None:
|
|
|
|
parent_element = emane_element
|
|
|
|
|
2018-08-21 22:26:59 +01:00
|
|
|
for address in netif.addrlist:
|
|
|
|
address_type = get_address_type(address)
|
2018-08-28 18:24:56 +01:00
|
|
|
add_address(parent_element, address_type, address, netif.name)
|