Generate pod.yaml from current context 93/41893/2
authorRoss Brattain <ross.b.brattain@intel.com>
Tue, 12 Sep 2017 16:41:45 +0000 (09:41 -0700)
committerRoss Brattain <ross.b.brattain@intel.com>
Fri, 15 Sep 2017 22:32:11 +0000 (15:32 -0700)
We want to generate pod.yaml from Heat contexts so we can
re-use the context without destroying it.

But we don't have node role information and it doesn't
make sense in this case, so make the role optional.

Since we changed Heat to use pkey instead of key_filename,
we can embed the pkey into the pod.yaml, but we have
to make sure to convert the pkey to string, in case
it is a RSAKey object

Change-Id: Ibefcfbd8236e68013a704c39964cb870da825da8
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
yardstick/benchmark/contexts/heat.py
yardstick/benchmark/contexts/node.py
yardstick/benchmark/core/task.py
yardstick/benchmark/scenarios/networking/vnf_generic.py
yardstick/ssh.py

index c7586ab..2f3cc5a 100644 (file)
@@ -442,6 +442,8 @@ class HeatContext(Context):
             "routing_table": self.generate_routing_table(server),
             # empty IPv6 routing table
             "nd_route_tbl": [],
+            # we want to save the contex name so we can generate pod.yaml
+            "name": server.name,
         }
         # Target server may only have private_ip
         if server.public_ip:
index 250032e..ffc82c8 100644 (file)
@@ -74,11 +74,11 @@ class NodeContext(Context):
 
         self.nodes.extend(cfg["nodes"])
         self.controllers.extend([node for node in cfg["nodes"]
-                                 if node["role"] == "Controller"])
+                                 if node.get("role") == "Controller"])
         self.computes.extend([node for node in cfg["nodes"]
-                              if node["role"] == "Compute"])
+                              if node.get("role") == "Compute"])
         self.baremetals.extend([node for node in cfg["nodes"]
-                                if node["role"] == "Baremetal"])
+                                if node.get("role") == "Baremetal"])
         LOG.debug("Nodes: %r", self.nodes)
         LOG.debug("Controllers: %r", self.controllers)
         LOG.debug("Computes: %r", self.computes)
index a8447e2..75703cf 100644 (file)
@@ -362,6 +362,7 @@ class Task(object):     # pragma: no cover
             context_cfg["nodes"] = parse_nodes_with_context(scenario_cfg)
             context_cfg["networks"] = get_networks_from_nodes(
                 context_cfg["nodes"])
+
         runner = base_runner.Runner.get(runner_cfg)
 
         LOG.info("Starting runner of type '%s'", runner_cfg["type"])
index ada9212..18ff404 100644 (file)
@@ -25,9 +25,11 @@ import re
 from itertools import chain
 
 import six
+import yaml
 from collections import defaultdict
 
 from yardstick.benchmark.scenarios import base
+from yardstick.common.constants import LOG_DIR
 from yardstick.common.utils import import_modules_from_package, itersubclasses
 from yardstick.common.yaml_loader import yaml_load
 from yardstick.network_services.collector.subscriber import Collector
@@ -364,6 +366,36 @@ class NetworkServiceTestCase(base.Scenario):
                 'ifindex': netdev['ifindex'],
             })
 
+    def _generate_pod_yaml(self):
+        context_yaml = os.path.join(LOG_DIR, "pod-{}.yaml".format(self.scenario_cfg['task_id']))
+        # convert OrderedDict to a list
+        # pod.yaml nodes is a list
+        nodes = []
+        for node in self.context_cfg["nodes"].values():
+            # name field is required
+            # remove context suffix
+            node['name'] = node['name'].split('.')[0]
+            nodes.append(node)
+        nodes = self._convert_pkeys_to_string(nodes)
+        pod_dict = {
+            "nodes": nodes,
+            "networks": self.context_cfg["networks"]
+        }
+        with open(context_yaml, "w") as context_out:
+            yaml.safe_dump(pod_dict, context_out, default_flow_style=False,
+                           explicit_start=True)
+
+    @staticmethod
+    def _convert_pkeys_to_string(nodes):
+        # make copy because we are mutating
+        nodes = nodes[:]
+        for i, node in enumerate(nodes):
+            try:
+                nodes[i] = dict(node, pkey=ssh.convert_key_to_str(node["pkey"]))
+            except KeyError:
+                pass
+        return nodes
+
     TOPOLOGY_REQUIRED_KEYS = frozenset({
         "vpci", "local_ip", "netmask", "local_mac", "driver"})
 
@@ -400,6 +432,8 @@ class NetworkServiceTestCase(base.Scenario):
                         "Require interface fields '%s' not found, topology file "
                         "corrupted" % ', '.join(missing))
 
+        # we have to generate pod.yaml here so we have vpci and driver
+        self._generate_pod_yaml()
         # 3. Use topology file to find connections & resolve dest address
         self._resolve_topology()
         self._update_context_with_topology()
index bb715e4..e98ee98 100644 (file)
@@ -64,6 +64,7 @@ Eventlet:
 """
 from __future__ import absolute_import
 import os
+import io
 import select
 import socket
 import time
@@ -81,6 +82,14 @@ from yardstick.common.utils import try_int
 from yardstick.network_services.utils import provision_tool
 
 
+def convert_key_to_str(key):
+    if not isinstance(key, (paramiko.RSAKey, paramiko.DSSKey)):
+        return key
+    k = io.StringIO()
+    key.write_private_key(k)
+    return k.getvalue()
+
+
 class SSHError(Exception):
     pass