HPENetworking / topology_docker

Docker based Platform Engine plugin for the Topology Modular Framework
https://topology-docker.readthedocs.io/
Apache License 2.0
2 stars 15 forks source link

hostname command in switches #10

Closed DanielBaldelomar closed 8 years ago

DanielBaldelomar commented 8 years ago

When try to execute the following command

sw1('hostname CT-TEST')

The test failed, because I am changing the prompt.

ocelotl commented 8 years ago

Don't change the prompt then, maybe?

ocelotl commented 8 years ago

Is your test supposed to change the prompt?

DanielBaldelomar commented 8 years ago

Yes, it is, and when I try to do it, I have the following output:

2016-02-03T10:10:43.928870 [sw1].send_command(hostname CT-TEST) ::

2016-02-03T10:10:44.038668 [sw1].send_command(end) ::
FAILED

================================================================================== FAILURES ===================================================================================
_______________________________________________________________________________ test_cfgdbutil ________________________________________________________________________________

topology = <topology.manager.TopologyManager object at 0x7f2dd03c63c8>, step = <topology.pytest.plugin.StepLogger object at 0x7f2dcf2f4550>

    def test_cfgdbutil(topology, step):
        sw1 = topology.get('sw1')

        assert sw1 is not None

        step("### Test cfgdbutils show commands ###")
        sw1('configure terminal')
        sw1('lldp holdtime 9')
        sw1('radius-server host 1.1.1.1')
        sw1('end')
        sw1('copy running-config startup-config')
        output = sw1('show startup-config')

        assert "lldp holdtime 9" in output and \
               "radius-server host 1.1.1.1" in output, \
               "Failed: To fetch startup configuration"

        """
        step("### Test to show startup config in json ###")
        output = sw1('show startup-config json')
        output = output[output.index('{'):]
        output = output[:output.rindex('}') + 1]

        parsed = json.loads(output)
        system = parsed["System"]
        radius_servers = system["radius_servers"]

        assert "1.1.1.1" in radius_servers,
               "Failed: To fetch startup config in json"
        """

        step("####   Delete startup config saved in configdb   ###")
        output = sw1('cfgdbutil delete startup-config', shell='bash')

        assert "success" in output, "Failed: Delete startup configuration"

        step("### Test copy running to startup config ###")
        sw1('configure terminal')
        sw1('hostname CT-TEST')
>       sw1('end')

../../../test/ops-cfgd/test_cfgdbutil.py:71: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../src/topology/lib/topology/platforms/base.py:211: in __call__
    return self.send_command(cmd, shell=shell, silent=silent)
../src/topology/lib/topology/platforms/base.py:339: in send_command
    response = self._shells[shell](cmd)
../lib/python3.4/site-packages/topology_docker/shell.py:68: in __call__
    self._spawn.expect(self._prompt, timeout=self._timeout)
../lib/python3.4/site-packages/pexpect/spawnbase.py:315: in expect
    timeout, searchwindowsize, async)
../lib/python3.4/site-packages/pexpect/spawnbase.py:339: in expect_list
    return exp.expect_loop(timeout)
../lib/python3.4/site-packages/pexpect/expect.py:104: in expect_loop
    return self.timeout(e)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <pexpect.expect.Expecter object at 0x7f2dcf2a3e80>, err = TIMEOUT('Timeout exceeded.',)

    def timeout(self, err=None):
        spawn = self.spawn
        from . import TIMEOUT

        spawn.before = spawn.buffer
        spawn.after = TIMEOUT
        index = self.searcher.timeout_index
        if index >= 0:
            spawn.match = TIMEOUT
            spawn.match_index = index
            return index
        else:
            spawn.match = None
            spawn.match_index = None
            msg = str(spawn)
            if err is not None:
                msg = str(err) + '\n' + msg
>           raise TIMEOUT(msg)
E           pexpect.exceptions.TIMEOUT: Timeout exceeded.
E           <pexpect.pty_spawn.spawn object at 0x7f2dd03c6588>
E           command: /usr/bin/docker
E           args: ['/usr/bin/docker', 'exec', '-i', '-t', '56f65537d50eb047218731a92ee8270c9b8e17fe95bceb570cf4eea585a0b934', 'vtysh']
E           searcher: None
E           buffer (last 100 chars): b' end\r\r\nCT-TEST# '
E           before (last 100 chars): b' end\r\r\nCT-TEST# '
E           after: <class 'pexpect.exceptions.TIMEOUT'>
E           match: None
E           match_index: None
E           exitstatus: None
E           flag_eof: False
E           pid: 20236
E           child_fd: 10
E           closed: False
E           timeout: 30
E           delimiter: <class 'pexpect.exceptions.EOF'>
E           logfile: None
E           logfile_read: None
E           logfile_send: None
E           maxread: 2000
E           ignorecase: False
E           searchwindowsize: None
E           delaybeforesend: 0.05
E           delayafterclose: 0.1
E           delayafterterminate: 0.1

../lib/python3.4/site-packages/pexpect/expect.py:68: TIMEOUT
--------------------------------------------- generated xml file: /users/baldelom/HALON2/openswitch_tests/.tox/py34/tmp/tests.xml ---------------------------------------------
========================================================================== slowest 10 test durations ==========================================================================
37.69s call     test/ops-cfgd/test_cfgdbutil.py::test_cfgdbutil
10.28s teardown test/ops-cfgd/test_cfgdbutil.py::test_cfgdbutil
8.06s setup    test/ops-cfgd/test_cfgdbutil.py::test_cfgdbutil
================================================================== 12 tests deselected by '-ktest_cfgdbutil' ==================================================================
================================================================== 1 failed, 12 deselected in 56.43 seconds ===================================================================
ERROR: InvocationError: '/users/baldelom/HALON2/openswitch_tests/.tox/py34/bin/py.test --random --durations=10 --junitxml=tests.xml --topology-nml-dir topologies --topology-plot-dir topologies --topology-plot-format svg --topology-platform=docker -k test_cfgdbutil -s -v /users/baldelom/HALON2/openswitch_tests/test'
___________________________________________________________________________________ summary ___________________________________________________________________________________
ERROR:   py34: commands failed
ocelotl commented 8 years ago

Thanks, much better. This issue seems related to a regex that is too restrictive, will investigate.

carlos-jenkins commented 8 years ago

@ocelotl not very much about the regular expression being too restrictive, more about the unpredictability of the prompt matching, which we have seen as problematic in other OpenSwitch related tests.

We can take into consideration the pexpect ssh helper pxssh's set_unique_prompt() call.

This call allows to set the prompt of a bash shell to a constant value during the pexpect session. Now, we can emulate that for bash shells, but the problem on the vytsh prompt will remain.

ocelotl commented 8 years ago

Handling prompt matching in a satisfactory way requires a a deeper change in the framework itself and also support for precise prompt changing in the involved shells. Meanwhile, this can serve as a workaround for this issue:

I tried with this image and found out that after calling hostname a second enter key press is needed for the prompt to be updated:

ocelotl@stallman:~/private/openswitch_tests/test$ docker run --privileged -v /tmp:/tmp -v /dev/log:/dev/log -v /sys/fs/cgroup:/sys/fs/cgroup openswitch:2016010100 /sbin/init
 &                                                                                                                                                                           
[2] 22388
ocelotl@stallman:~/private/openswitch_tests/test$ docker ps
CONTAINER ID        IMAGE                   COMMAND             CREATED              STATUS              PORTS               NAMES
b0c4d4fd5025        openswitch:2016010100   "/sbin/init"        10 seconds ago       Up 10 seconds                           happy_galileo
5aba68e7302c        openswitch:2016010100   "/sbin/init"        About a minute ago   Up About a minute                       stupefied_archimedes
ocelotl@stallman:~/private/openswitch_tests/test$ docker exec -t -i b0c4d4fd5025 vtysh
switch# configure terminal
switch(config)# hostname new_hostname
switch(config)# 
new_hostname(config)# exit
new_hostname# exit

Considering this, you can use this workaround (notice how the promtp is changhed after calling hostname):

TOPOLOGY = """
[type=openswitch name="OpenSwitch 1" image="openswitch:2016010100"] ops1
"""

def test_hostname(topology):
    """
    This is a test case that uses vtysh hostname command.
    """
    ops1 = topology.get('ops1')
    ops1('configure terminal')
    ops1('hostname new_hostname')
    ops1._shells['vtysh']._prompt = (
        '(^|\n)new_hostname(\\([\\-a-zA-Z0-9]*\\))?#'
    )
    ops1('exit')
    ops1('show vlan 1')
DanielBaldelomar commented 8 years ago

Ok Hurtado, thanks a lot, this fix works fine.

ocelotl commented 8 years ago

Closing now, then.