From ae58801332baaa66ea71c9e233e23f0f68a0afe2 Mon Sep 17 00:00:00 2001 From: stevenvanrossem Date: Tue, 6 Jun 2017 10:33:19 +0200 Subject: [PATCH] cleanup networking api, rest and cli and unittest --- src/emuvim/api/openstack/__init__.py | 0 src/emuvim/api/openstack/chain_api.py | 0 src/emuvim/api/openstack/compute.py | 0 src/emuvim/api/openstack/docker_util.py | 0 src/emuvim/api/openstack/heat_parser.py | 0 src/emuvim/api/openstack/ip_handler.py | 0 src/emuvim/api/openstack/manage.py | 0 .../api/openstack/openstack_api_endpoint.py | 0 .../openstack/openstack_dummies/__init__.py | 0 .../openstack_dummies/base_openstack_dummy.py | 0 .../openstack_dummies/glance_dummy_api.py | 0 .../openstack_dummies/heat_dummy_api.py | 0 .../openstack_dummies/keystone_dummy_api.py | 0 .../openstack_dummies/neutron_dummy_api.py | 0 .../openstack_dummies/nova_dummy_api.py | 0 .../api/openstack/resources/__init__.py | 0 src/emuvim/api/openstack/resources/image.py | 0 .../openstack/resources/instance_flavor.py | 0 .../api/openstack/resources/load_balancer.py | 0 src/emuvim/api/openstack/resources/model.py | 0 src/emuvim/api/openstack/resources/net.py | 0 src/emuvim/api/openstack/resources/port.py | 0 .../api/openstack/resources/resource.py | 0 src/emuvim/api/openstack/resources/router.py | 0 src/emuvim/api/openstack/resources/server.py | 0 src/emuvim/api/openstack/resources/stack.py | 0 .../api/openstack/resources/template.py | 0 src/emuvim/api/rest/network.py | 1 - src/emuvim/cli/rest/network.py | 16 +++--- src/emuvim/dashboard/js/graph.json | 0 src/emuvim/dcemulator/net.py | 18 ++++++- .../demo_emulator_mano_integration.py | 2 +- src/emuvim/examples/demo_topo_3pop.py | 2 +- src/emuvim/examples/profiling.py | 0 src/emuvim/test/api_base.py | 2 +- src/emuvim/test/test-initial-template.yml | 0 src/emuvim/test/test-scaleout-template.yml | 0 src/emuvim/test/unittests/test_emulator.py | 51 +++++++++++++++++++ .../test_heatapi_keystone_get_token.json | 0 .../test_heatapi_template_chaining.json | 0 .../test_heatapi_template_create_stack.json | 0 .../test_heatapi_template_update_stack.json | 0 src/emuvim/test/unittests/test_restapi.py | 18 +++---- 43 files changed, 88 insertions(+), 22 deletions(-) mode change 100644 => 100755 src/emuvim/api/openstack/__init__.py mode change 100644 => 100755 src/emuvim/api/openstack/chain_api.py mode change 100644 => 100755 src/emuvim/api/openstack/compute.py mode change 100644 => 100755 src/emuvim/api/openstack/docker_util.py mode change 100644 => 100755 src/emuvim/api/openstack/heat_parser.py mode change 100644 => 100755 src/emuvim/api/openstack/ip_handler.py mode change 100644 => 100755 src/emuvim/api/openstack/manage.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_api_endpoint.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/__init__.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/base_openstack_dummy.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/glance_dummy_api.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/heat_dummy_api.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/keystone_dummy_api.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py mode change 100644 => 100755 src/emuvim/api/openstack/openstack_dummies/nova_dummy_api.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/__init__.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/image.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/instance_flavor.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/load_balancer.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/model.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/net.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/port.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/resource.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/router.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/server.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/stack.py mode change 100644 => 100755 src/emuvim/api/openstack/resources/template.py mode change 100644 => 100755 src/emuvim/dashboard/js/graph.json mode change 100644 => 100755 src/emuvim/examples/demo_emulator_mano_integration.py mode change 100644 => 100755 src/emuvim/examples/profiling.py mode change 100644 => 100755 src/emuvim/test/test-initial-template.yml mode change 100644 => 100755 src/emuvim/test/test-scaleout-template.yml mode change 100644 => 100755 src/emuvim/test/unittests/test_heatapi_keystone_get_token.json mode change 100644 => 100755 src/emuvim/test/unittests/test_heatapi_template_chaining.json mode change 100644 => 100755 src/emuvim/test/unittests/test_heatapi_template_create_stack.json mode change 100644 => 100755 src/emuvim/test/unittests/test_heatapi_template_update_stack.json diff --git a/src/emuvim/api/openstack/__init__.py b/src/emuvim/api/openstack/__init__.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/chain_api.py b/src/emuvim/api/openstack/chain_api.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/compute.py b/src/emuvim/api/openstack/compute.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/docker_util.py b/src/emuvim/api/openstack/docker_util.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/heat_parser.py b/src/emuvim/api/openstack/heat_parser.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/ip_handler.py b/src/emuvim/api/openstack/ip_handler.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/manage.py b/src/emuvim/api/openstack/manage.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_api_endpoint.py b/src/emuvim/api/openstack/openstack_api_endpoint.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/__init__.py b/src/emuvim/api/openstack/openstack_dummies/__init__.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/base_openstack_dummy.py b/src/emuvim/api/openstack/openstack_dummies/base_openstack_dummy.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/glance_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/glance_dummy_api.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/heat_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/heat_dummy_api.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/keystone_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/keystone_dummy_api.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/openstack_dummies/nova_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/nova_dummy_api.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/__init__.py b/src/emuvim/api/openstack/resources/__init__.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/image.py b/src/emuvim/api/openstack/resources/image.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/instance_flavor.py b/src/emuvim/api/openstack/resources/instance_flavor.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/load_balancer.py b/src/emuvim/api/openstack/resources/load_balancer.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/model.py b/src/emuvim/api/openstack/resources/model.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/net.py b/src/emuvim/api/openstack/resources/net.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/port.py b/src/emuvim/api/openstack/resources/port.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/resource.py b/src/emuvim/api/openstack/resources/resource.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/router.py b/src/emuvim/api/openstack/resources/router.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/server.py b/src/emuvim/api/openstack/resources/server.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/stack.py b/src/emuvim/api/openstack/resources/stack.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/openstack/resources/template.py b/src/emuvim/api/openstack/resources/template.py old mode 100644 new mode 100755 diff --git a/src/emuvim/api/rest/network.py b/src/emuvim/api/rest/network.py index bce10fc..0479ee6 100755 --- a/src/emuvim/api/rest/network.py +++ b/src/emuvim/api/rest/network.py @@ -90,7 +90,6 @@ class NetworkAction(Resource): if data is None: data = {} - logging.info("data: {}".format(data)) vnf_src_name = data.get("vnf_src_name") vnf_dst_name = data.get("vnf_dst_name") vnf_src_interface = data.get("vnf_src_interface") diff --git a/src/emuvim/cli/rest/network.py b/src/emuvim/cli/rest/network.py index b4a1a89..82fe99f 100755 --- a/src/emuvim/cli/rest/network.py +++ b/src/emuvim/cli/rest/network.py @@ -26,10 +26,8 @@ acknowledge the contributions of their colleagues of the SONATA partner consortium (www.sonata-nfv.eu). """ from requests import get,put, delete -import pprint import argparse -pp = pprint.PrettyPrinter(indent=4) class RestApiClient(): @@ -57,7 +55,7 @@ class RestApiClient(): response = put("{0}/restapi/network".format(args.get("endpoint")), params=params) - pp.pprint(response.text) + print(self._nice_print(response.text)) def remove(self, args): params = self._create_dict( @@ -73,7 +71,7 @@ class RestApiClient(): response = delete("{0}/restapi/network".format(args.get("endpoint")), params=params) - pp.pprint(response.text) + print(self._nice_print(response.text)) def _parse_vnf_name(self, vnf_name_str): vnf_name = vnf_name_str.split(':')[0] @@ -90,6 +88,12 @@ class RestApiClient(): def _create_dict(self, **kwargs): return kwargs + def _nice_print(self, text): + # some modules seem to return unicode strings where newlines, other special characters are escaped + text = str(text).replace('\\n', '\n') + text = str(text).replace('\\"', '"') + return text + parser = argparse.ArgumentParser(description='son-emu-cli network') parser.add_argument( "command", @@ -108,7 +112,7 @@ parser.add_argument( "--weight", "-w", dest="weight", help="weight edge attribute to calculate the path") parser.add_argument( - "--priority", "-p", dest="priority", default="0", + "--priority", "-p", dest="priority", default="1000", help="priority of flow rule") parser.add_argument( "--match", "-m", dest="match", @@ -117,7 +121,7 @@ parser.add_argument( "--bidirectional", "-b", dest="bidirectional", action='store_true', help="add/remove the flow entries from src to dst and back") parser.add_argument( - "--cookie", "-c", dest="cookie", + "--cookie", "-c", dest="cookie", default="10", help="cookie for this flow, as easy to use identifier (eg. per tenant/service)") parser.add_argument( "--endpoint", "-e", dest="endpoint", diff --git a/src/emuvim/dashboard/js/graph.json b/src/emuvim/dashboard/js/graph.json old mode 100644 new mode 100755 diff --git a/src/emuvim/dcemulator/net.py b/src/emuvim/dcemulator/net.py index 5dfcbcd..7efb3f0 100755 --- a/src/emuvim/dcemulator/net.py +++ b/src/emuvim/dcemulator/net.py @@ -33,6 +33,7 @@ from subprocess import Popen import re import requests import os +import json from mininet.net import Containernet from mininet.node import Controller, DefaultController, OVSSwitch, OVSKernelSwitch, Docker, RemoteController @@ -50,6 +51,11 @@ LOG.setLevel(logging.DEBUG) # default CPU period used for cpu percentage-based cfs values (microseconds) CPU_PERIOD = 1000000 +# default priority setting for added flow-rules +DEFAULT_PRIORITY = 1000 +# default cookie number for new flow-rules +DEFAULT_COOKIE = 10 + class DCNetwork(Containernet): """ Wraps the original Mininet/Containernet class and provides @@ -710,7 +716,15 @@ class DCNetwork(Containernet): switch_inport_nr = self.DCNetwork_graph[current_hop][next_hop][0]['dst_port_nr'] current_hop = next_hop - return "path {2} between {0} and {1}".format(vnf_src_name, vnf_dst_name, cmd) + flow_options = { + 'priority':kwargs.get('priority', DEFAULT_PRIORITY), + 'cookie':kwargs.get('cookie', DEFAULT_COOKIE), + 'vlan':kwargs['vlan'], + 'path':kwargs['path'], + 'match_input':kwargs.get('match') + } + flow_options_str = json.dumps(flow_options, indent=1) + return "success: {2} between {0} and {1} with options: {3}".format(vnf_src_name, vnf_dst_name, cmd, flow_options_str) def _set_flow_entry_ryu_rest(self, node, switch_inport_nr, switch_outport_nr, **kwargs): match = 'in_port=%s' % switch_inport_nr @@ -722,7 +736,7 @@ class DCNetwork(Containernet): index = kwargs.get('pathindex') vlan = kwargs.get('vlan') - priority = kwargs.get('priority') + priority = kwargs.get('priority', DEFAULT_PRIORITY) # flag to not set the ovs port vlan tag skip_vlan_tag = kwargs.get('skip_vlan_tag') # table id to put this flowentry diff --git a/src/emuvim/examples/demo_emulator_mano_integration.py b/src/emuvim/examples/demo_emulator_mano_integration.py old mode 100644 new mode 100755 index 992d972..f13b9d3 --- a/src/emuvim/examples/demo_emulator_mano_integration.py +++ b/src/emuvim/examples/demo_emulator_mano_integration.py @@ -20,7 +20,7 @@ class DemoTopology(DCNetwork): Initialize multi PoP emulator network. """ super(DemoTopology, self).__init__( - monitor=False, + monitor=True, enable_learning=True ) # define members for later use diff --git a/src/emuvim/examples/demo_topo_3pop.py b/src/emuvim/examples/demo_topo_3pop.py index 8020fc8..aee5f91 100755 --- a/src/emuvim/examples/demo_topo_3pop.py +++ b/src/emuvim/examples/demo_topo_3pop.py @@ -47,7 +47,7 @@ logging.basicConfig(level=logging.INFO) def create_topology1(): # create topology - net = DCNetwork(controller=RemoteController, monitor=False, enable_learning=True) + net = DCNetwork(controller=RemoteController, monitor=True, enable_learning=True) dc1 = net.addDatacenter("dc1") dc2 = net.addDatacenter("dc2") dc3 = net.addDatacenter("dc3") diff --git a/src/emuvim/examples/profiling.py b/src/emuvim/examples/profiling.py old mode 100644 new mode 100755 diff --git a/src/emuvim/test/api_base.py b/src/emuvim/test/api_base.py index 57d4aa5..3464f45 100755 --- a/src/emuvim/test/api_base.py +++ b/src/emuvim/test/api_base.py @@ -68,7 +68,7 @@ class SimpleTestTopology(unittest.TestCase): specific controller functionality. """ self.net = DCNetwork(controller=controller, **kwargs) - self.api = RestApiEndpoint("127.0.0.1", 5001) + self.api = RestApiEndpoint("127.0.0.1", 5001, self.net) # add some switches # start from s1 because ovs does not like to have dpid = 0 # and switch name-number is being used by mininet to set the dpid diff --git a/src/emuvim/test/test-initial-template.yml b/src/emuvim/test/test-initial-template.yml old mode 100644 new mode 100755 diff --git a/src/emuvim/test/test-scaleout-template.yml b/src/emuvim/test/test-scaleout-template.yml old mode 100644 new mode 100755 diff --git a/src/emuvim/test/unittests/test_emulator.py b/src/emuvim/test/unittests/test_emulator.py index b5612a1..94db55f 100755 --- a/src/emuvim/test/unittests/test_emulator.py +++ b/src/emuvim/test/unittests/test_emulator.py @@ -117,6 +117,57 @@ class testEmulatorTopology( SimpleTestTopology ): class testEmulatorNetworking( SimpleTestTopology ): + def testSDNChainingSingleService_withLearning(self): + """ + Create a two data centers and interconnect them with additional + switches between them. + Uses Ryu SDN controller. + Connect the Docker hosts to different datacenters and setup the links between. + """ + # create network + self.createNet( + nswitches=3, ndatacenter=2, nhosts=0, ndockers=0, + autolinkswitches=True, + controller=RemoteController, + enable_learning=True) + # setup links + self.net.addLink(self.dc[0], self.s[0]) + self.net.addLink(self.s[2], self.dc[1]) + # start Mininet network + self.startNet() + + # add compute resources + vnf1 = self.dc[0].startCompute("vnf1", network=[{'id':'intf1', 'ip':'10.0.10.1/24'}]) + vnf2 = self.dc[1].startCompute("vnf2", network=[{'id':'intf2', 'ip':'10.0.10.2/24'}]) + # check number of running nodes + self.assertTrue(len(self.getContainernetContainers()) == 2) + self.assertTrue(len(self.net.hosts) == 2) + self.assertTrue(len(self.net.switches) == 5) + # check status + # check get status + s1 = self.dc[0].containers.get("vnf1").getStatus() + print s1 + self.assertTrue(s1["name"] == "vnf1") + self.assertTrue(s1["state"]["Running"]) + self.assertTrue(s1["network"][0]['intf_name'] == 'intf1') + self.assertTrue(s1["network"][0]['ip'] == '10.0.10.1/24') + + s2 = self.dc[1].containers.get("vnf2").getStatus() + print s2 + self.assertTrue(s2["name"] == "vnf2") + self.assertTrue(s2["state"]["Running"]) + self.assertTrue(s2["network"][0]['intf_name'] == 'intf2') + self.assertTrue(s2["network"][0]['ip'] == '10.0.10.2/24') + + # should be connected because learning = True + self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0) + # setup links + self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='add-flow') + # should still be connected + self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0) + # stop Mininet network + self.stopNet() + def testSDNChainingSingleService(self): """ Create a two data centers and interconnect them with additional diff --git a/src/emuvim/test/unittests/test_heatapi_keystone_get_token.json b/src/emuvim/test/unittests/test_heatapi_keystone_get_token.json old mode 100644 new mode 100755 diff --git a/src/emuvim/test/unittests/test_heatapi_template_chaining.json b/src/emuvim/test/unittests/test_heatapi_template_chaining.json old mode 100644 new mode 100755 diff --git a/src/emuvim/test/unittests/test_heatapi_template_create_stack.json b/src/emuvim/test/unittests/test_heatapi_template_create_stack.json old mode 100644 new mode 100755 diff --git a/src/emuvim/test/unittests/test_heatapi_template_update_stack.json b/src/emuvim/test/unittests/test_heatapi_template_update_stack.json old mode 100644 new mode 100755 diff --git a/src/emuvim/test/unittests/test_restapi.py b/src/emuvim/test/unittests/test_restapi.py index ea0b693..268b12b 100755 --- a/src/emuvim/test/unittests/test_restapi.py +++ b/src/emuvim/test/unittests/test_restapi.py @@ -92,14 +92,19 @@ class testRestApi(SimpleTestTopology): print('network add vnf1 vnf2->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli network add -src vnf1 -dst vnf2 -b -c 10", shell=True) + output = subprocess.check_output("son-emu-cli network add -src vnf1 -dst vnf2 -b -c 10", shell=True) + self.assertTrue("add-flow" in output) + self.assertTrue("success" in output) + print('network remove vnf1 vnf2->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli network remove -src vnf1 -dst vnf2 -b", shell=True) + output = subprocess.check_output("son-emu-cli network remove -src vnf1 -dst vnf2 -b", shell=True) + self.assertTrue("del-flows" in output) + self.assertTrue("success" in output) print('>>>>> checking --> son-emu-cli compute stop -d datacenter0 -n vnf2 ->>>>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli compute stop -d datacenter0 -n vnf2", shell=True) + output = subprocess.check_output("son-emu-cli compute stop -d datacenter0 -n vnf2", shell=True) # check number of running nodes self.assertTrue(len(self.getContainernetContainers()) == 2) @@ -111,7 +116,6 @@ class testRestApi(SimpleTestTopology): print('>>>>> checking --> son-emu-cli compute list ->>>>>>>>>>>>>>>>>>>>>>>>>>>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli compute list", shell=True) output = subprocess.check_output("son-emu-cli compute list", shell=True) # check datacenter list result @@ -119,7 +123,6 @@ class testRestApi(SimpleTestTopology): print('>>>>> checking --> son-emu-cli compute status -d datacenter0 -n vnf1 ->>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli compute status -d datacenter0 -n vnf1", shell=True) output = subprocess.check_output("son-emu-cli compute status -d datacenter0 -n vnf1", shell=True) output = ast.literal_eval(output) @@ -129,18 +132,13 @@ class testRestApi(SimpleTestTopology): print('>>>>> checking --> son-emu-cli datacenter list ->>>>>>>>>>>>>>>>>>>>>>>>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli datacenter list", shell=True) output = subprocess.check_output("son-emu-cli datacenter list", shell=True) - # check datacenter list result - self.assertTrue("datacenter0" in output) print('->>>>> checking --> son-emu-cli datacenter status -d datacenter0 ->>>>>>>>') print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') - subprocess.call("son-emu-cli datacenter status -d datacenter0", shell=True) output = subprocess.check_output("son-emu-cli datacenter status -d datacenter0", shell=True) - # check datacenter status result self.assertTrue("datacenter0" in output) -- 2.25.1