Ejemplo n.º 1
0
 def setUp(self):
     ''' Instantiate the CvpClient class.
         Log messages to the /tmp/TestCvpClient.log
     '''
     super(TestCvpClient, self).setUp()
     self.clnt = CvpClient(filename='/tmp/TestCvpClient.log')
     self.assertIsNotNone(self.clnt)
Ejemplo n.º 2
0
def connect(module):
    ''' Connects to CVP device using user provided credentials from playbook.

    :param module: Ansible module with parameters and client connection.
    :return: CvpClient object with connection instantiated.
    '''
    client = CvpClient()
    try:
        client.connect([module.params['host']],
                       module.params['username'],
                       module.params['password'],
                       protocol=module.params['protocol'],
                       port=module.params['port'])
    except CvpLoginError as e:
        module.fail_json(msg=str(e))
    return client
Ejemplo n.º 3
0
 def setUp(self):
     """ Setup for CvpClient unittests
     """
     self.clnt = CvpClient()
     nodes = ['1.1.1.1']
     self.clnt.nodes = nodes
     self.clnt.node_cnt = len(nodes)
     self.clnt.node_pool = cycle(nodes)
Ejemplo n.º 4
0
 def _change_passwd(self, nodes, username, old_password, new_password):
     ''' Helper method to change the user password on CVP.
     '''
     # Create a new connection to handle the request.
     clnt = CvpClient(filename='/tmp/TestCvpClient.log')
     clnt.connect(nodes, username, old_password)
     data = {
         'user': {
             'userId': username,
             'password': new_password,
             'email': '*****@*****.**',
             'userStatus': 'Enabled',
         },
         'roles': [
             'network-admin'
         ]
     }
     result = clnt.post("/user/updateUser.do?userId=%s" % username, data)
     self.assertEqual('success', result['data'])
Ejemplo n.º 5
0
 def test_clnt_init_log_level(self):
     ''' Verify CvpClient init with setting log level
     '''
     clnt = CvpClient(log_level='DEBUG')
     self.assertIsNotNone(clnt)
     self.assertEqual(clnt.log.getEffectiveLevel(), logging.DEBUG)
#!/usr/bin/env python

# See getting started:
# https://github.com/aristanetworks/cvprac#example
# sudo pip install cvprac

import sys
import pprint

# should just fix this
import urllib3
urllib3.disable_warnings()

from cvprac.cvp_client import CvpClient
clnt = CvpClient()

if len(sys.argv) != 2:
    print "Usage: python sys.argv[0] ip_of_cvp"
    sys.exit(1)
else:
    cvphost = sys.argv[1]

clnt.connect([cvphost], 'arista', 'arista')
device_info = clnt.api.get_device_by_name('leaf1.arista.test')

pprint.pprint(device_info)
Ejemplo n.º 7
0
 def test_clnt_init(self):
     ''' Verify CvpClient init
     '''
     clnt = CvpClient()
     self.assertIsNotNone(clnt)
Ejemplo n.º 8
0
from pprint import pprint
from cvprac.cvp_client import CvpClient
from cvprac.cvp_api import CvpApi
import urllib3
import requests

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning
                         )  # This will disable invalid cert warnings

clnt = CvpClient()

clnt.connect(['cvp.lab.local'], 'jpatterson', 'P3pp3r101!')

result = clnt.get('/cvpInfo/getCvpInfo.do')

test1 = clnt.get(
    '/cvpservice/snapshot/getSnapshots.do?startIndex=0&endIndex=0')

pprint(result)
Ejemplo n.º 9
0
class TestCvpClient(DutSystemTest):
    ''' Test cases for the CvpClient class.
    '''
    # pylint: disable=too-many-public-methods
    # pylint: disable=invalid-name
    NEW_PASSWORD = '******'

    def setUp(self):
        ''' Instantiate the CvpClient class.
            Log messages to the /tmp/TestCvpClient.log
        '''
        super(TestCvpClient, self).setUp()
        self.clnt = CvpClient(filename='/tmp/TestCvpClient.log')
        self.assertIsNotNone(self.clnt)

    def tearDown(self):
        ''' Destroy the CvpClient class.
        '''
        super(TestCvpClient, self).tearDown()
        self.clnt = None

    def _change_passwd(self, nodes, username, old_password, new_password):
        ''' Helper method to change the user password on CVP.
        '''
        # Create a new connection to handle the request.
        clnt = CvpClient(filename='/tmp/TestCvpClient.log')
        clnt.connect(nodes, username, old_password)
        data = {
            'user': {
                'userId': username,
                'password': new_password,
                'email': '*****@*****.**',
                'userStatus': 'Enabled',
            },
            'roles': ['network-admin']
        }
        result = clnt.post("/user/updateUser.do?userId=%s" % username, data)
        self.assertEqual('success', result['data'])

    def test_clnt_init(self):
        ''' Verify CvpClient init
        '''
        clnt = CvpClient()
        self.assertIsNotNone(clnt)
        self.assertEqual(clnt.log.getEffectiveLevel(), logging.INFO)

    def test_clnt_init_syslog(self):
        ''' Verify CvpClient init with syslog argument
        '''
        clnt = CvpClient(syslog=True)
        self.assertIsNotNone(clnt)

    def test_clnt_init_syslog_filename(self):
        ''' Verify CvpClient init with syslog and filename argument
        '''
        logfile = '/tmp/foo'
        clnt = CvpClient(syslog=True, logger='cvpracTmp', filename=logfile)
        self.assertIsNotNone(clnt)
        os.remove(logfile)

    def test_clnt_init_log_level(self):
        ''' Verify CvpClient init with setting log level
        '''
        clnt = CvpClient(log_level='DEBUG')
        self.assertIsNotNone(clnt)
        self.assertEqual(clnt.log.getEffectiveLevel(), logging.DEBUG)

    def test_set_log_level(self):
        ''' Verify changing/setting of log level using client setter method
        '''
        self.clnt.set_log_level('DEBUG')
        self.assertEqual(self.clnt.log.getEffectiveLevel(), logging.DEBUG)
        self.clnt.set_log_level('INFO')
        self.assertEqual(self.clnt.log.getEffectiveLevel(), logging.INFO)

    def test_set_log_level_invalid_value(self):
        ''' Verify an invalid log level value will default the log level to
            INFO
        '''
        self.clnt.set_log_level('blahblah')
        self.assertEqual(self.clnt.log.getEffectiveLevel(), logging.INFO)

    def test_connect_http_good(self):
        ''' Verify http connection succeeds to a single CVP node
            Uses default protocol and port.
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])

    def test_connect_https_good(self):
        ''' Verify https connection succeeds to a single CVP node
            Uses https protocol and port.
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])

    def test_connect_set_request_timeout(self):
        ''' Verify API request timeout is set when provided to
            client connect method.
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']],
                          dut['username'],
                          dut['password'],
                          request_timeout=34)
        self.assertEqual(self.clnt.api.request_timeout, 34)

    def test_connect_username_bad(self):
        ''' Verify connect fails with bad username.
        '''
        dut = self.duts[0]
        with self.assertRaises(CvpLoginError):
            self.clnt.connect([dut['node']], 'username', dut['password'])

    def test_connect_password_bad(self):
        ''' Verify connect fails with bad password.
        '''
        dut = self.duts[0]
        with self.assertRaises(CvpLoginError):
            self.clnt.connect([dut['node']], dut['username'], 'password')

    def test_connect_node_bad(self):
        ''' Verify connection fails to a single bogus CVP node
        '''
        with self.assertRaises(CvpLoginError):
            self.clnt.connect(['bogus'],
                              'username',
                              'password',
                              connect_timeout=1)

    def test_connect_non_cvp_node(self):
        ''' Verify connection fails to a non-CVP node
        '''
        with self.assertRaises(CvpLoginError):
            self.clnt.connect(['localhost'], 'username', 'password')

    def test_connect_all_nodes_bad(self):
        ''' Verify connection fails to a single bogus CVP node
        '''
        with self.assertRaises(CvpLoginError):
            self.clnt.connect(['bogus1', 'bogus2', 'bogus3'],
                              'username',
                              'password',
                              connect_timeout=1)

    def test_connect_n1_bad_n2_good(self):
        ''' Verify connect succeeds even if one node is bad
        '''
        dut = self.duts[0]
        self.clnt.connect(['bogus', dut['node']],
                          dut['username'],
                          dut['password'],
                          connect_timeout=5)

    def test_connect_nodes_arg_bad(self):
        ''' Verify non-list nodes argument raises a TypeError
        '''
        with self.assertRaises(TypeError):
            self.clnt.connect('bogus', 'username', 'password')

    def test_connect_port_bad(self):
        ''' Verify non default port for https raises an error if appliance is
            not configured for the port.
        '''
        dut = self.duts[0]
        with self.assertRaises(CvpLoginError):
            self.clnt.connect([dut['node']],
                              dut['username'],
                              dut['password'],
                              port=700)

    def test_get_not_connected(self):
        ''' Verify get with no connection raises a ValueError
        '''
        with self.assertRaises(ValueError):
            self.clnt.get('/bogus')

    def test_get(self):
        ''' Verify get of CVP info
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        self.assertIn('version', result)

    def test_get_recover_session(self):
        ''' Verify client(get) recovers session after logout
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        self.assertIn('version', result)

    def test_get_recover_session_bg(self):
        ''' Verify client(get) recovers session after logout for bad/good node
        '''
        dut = self.duts[0]
        self.clnt.connect(['bogus', dut['node']], dut['username'],
                          dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        self.assertIn('version', result)

    def test_get_cvp_error(self):
        ''' Verify get of bad CVP request returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        if self.clnt.apiversion is None:
            self.clnt.api.get_cvp_info()
        if self.clnt.apiversion == 'v1':
            with self.assertRaises(CvpRequestError):
                self.clnt.get('/aaa/getServerById.do')
        else:
            with self.assertRaises(CvpApiError):
                self.clnt.get('/aaa/getServerById.do')

    def test_get_cvp_url_bad(self):
        ''' Verify get with bad URL returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(CvpApiError):
            self.clnt.get('/aaa/bogus.do')

    def test_get_handle_timeout(self):
        ''' Verify get with bad URL returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(Timeout):
            self.clnt.get('/tasks/getTasks.do', timeout=0.0001)

    def test_get_except_fail_reconnect(self):
        ''' Verify exception raised if session fails and cannot be
            re-established.
        '''
        dut = self.duts[0]
        nodes = ['bogus', dut['node']]
        self.clnt.connect(nodes, dut['username'], dut['password'])
        # Change the password for the CVP user so that a session reconnect
        # to any node will fail
        self._change_passwd(nodes, dut['username'], dut['password'],
                            self.NEW_PASSWORD)

        try:
            # Logout to end the current session and force a reconnect for the
            # next request.
            result = self.clnt.post('/login/logout.do', None)
            self.assertIn('data', result)
            self.assertEqual('success', result['data'])

        except Exception as error:
            # Should not have had an exception.  Restore the CVP password
            # and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        try:
            # Try a get request and expect a CvpSessionLogOutError
            result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        except (CvpSessionLogOutError, CvpApiError) as error:
            pass
        except Exception as error:
            # Unexpected error, restore password and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        # Restore password
        self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                            dut['password'])

    def test_post_not_connected(self):
        ''' Verify post with no connection raises a ValueError
        '''
        with self.assertRaises(ValueError):
            self.clnt.post('/bogus', None)

    def test_post(self):
        ''' Verify post of CVP info
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])

    def test_post_recover_session(self):
        ''' Verify client(post) recovers session after logout
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertEqual('success', result['data'])

    def test_post_recover_session_bg(self):
        ''' Verify client(post) recovers session after logout for bad/good node
        '''
        dut = self.duts[0]
        self.clnt.connect(['bogus', dut['node']], dut['username'],
                          dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertEqual('success', result['data'])

    def test_post_cvp_bad_schema(self):
        ''' Verify post with bad schema returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        if self.clnt.apiversion is None:
            self.clnt.api.get_cvp_info()
        if self.clnt.apiversion == 'v1':
            with self.assertRaises(CvpApiError):
                self.clnt.post('/aaa/saveAAADetails.do', None)
        else:
            with self.assertRaises(CvpRequestError):
                self.clnt.post('/aaa/saveAAADetails.do', None)

    def test_post_cvp_url_bad(self):
        ''' Verify post with bad URL returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(CvpApiError):
            self.clnt.post('/aaa/bogus.do', None)

    def test_post_except_fail_reconn(self):
        ''' Verify exception raised if session fails and cannot be
            re-established.
        '''
        dut = self.duts[0]
        nodes = ['bogus', dut['node']]
        self.clnt.connect(nodes, dut['username'], dut['password'])
        # Change the password for the CVP user so that a session reconnect
        # to any node will fail
        self._change_passwd(nodes, dut['username'], dut['password'],
                            self.NEW_PASSWORD)

        try:
            # Logout to end the current session and force a reconnect for the
            # next request.
            result = self.clnt.post('/login/logout.do', None)
            self.assertIn('data', result)
            self.assertEqual('success', result['data'])

        except Exception as error:
            # Should not have had an exception.  Restore the CVP password
            # and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        try:
            # Try a post request and expect a CvpSessionLogOutError
            result = self.clnt.post('/login/logout.do', None)
        except (CvpSessionLogOutError, CvpApiError) as error:
            pass
        except Exception as error:
            # Unexpected error, restore password and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        # Restore password
        self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                            dut['password'])
Ejemplo n.º 10
0
class TestCvpClient(DutSystemTest):
    ''' Test cases for the CvpClient class.
    '''
    # pylint: disable=too-many-public-methods
    NEW_PASSWORD = '******'

    def setUp(self):
        ''' Instantiate the CvpClient class.
            Log messages to the /tmp/TestCvpClient.log
        '''
        super(TestCvpClient, self).setUp()
        self.clnt = CvpClient(filename='/tmp/TestCvpClient.log')
        self.assertIsNotNone(self.clnt)

    def tearDown(self):
        ''' Destroy the CvpClient class.
        '''
        super(TestCvpClient, self).tearDown()
        self.clnt = None

    def _change_passwd(self, nodes, username, old_password, new_password):
        ''' Helper method to change the user password on CVP.
        '''
        # Create a new connection to handle the request.
        clnt = CvpClient(filename='/tmp/TestCvpClient.log')
        clnt.connect(nodes, username, old_password)
        data = {
            'user': {
                'userId': username,
                'password': new_password,
                'email': '*****@*****.**',
                'userStatus': 'Enabled',
            },
            'roles': [
                'network-admin'
            ]
        }
        result = clnt.post("/user/updateUser.do?userId=%s" % username, data)
        self.assertEqual('success', result['data'])

    def test_clnt_init(self):
        ''' Verify CvpClient init
        '''
        clnt = CvpClient()
        self.assertIsNotNone(clnt)

    def test_clnt_init_syslog(self):
        ''' Verify CvpClient init with syslog argument
        '''
        clnt = CvpClient(syslog=True)
        self.assertIsNotNone(clnt)

    def test_clnt_init_syslog_filename(self):
        ''' Verify CvpClient init with syslog and filename argument
        '''
        logfile = '/tmp/foo'
        clnt = CvpClient(syslog=True, logger='cvpracTmp', filename=logfile)
        self.assertIsNotNone(clnt)
        os.remove(logfile)

    def test_connect_http_good(self):
        ''' Verify http connection succeeds to a single CVP node
            Uses default protocol and port.
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])

    def test_connect_https_good(self):
        ''' Verify https connection succeeds to a single CVP node
            Uses https protocol and port.
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'],
                          protocol='https')

    def test_connect_username_bad(self):
        ''' Verify connect fails with bad username.
        '''
        dut = self.duts[0]
        with self.assertRaises(CvpLoginError):
            self.clnt.connect([dut['node']], 'username', dut['password'])

    def test_connect_password_bad(self):
        ''' Verify connect fails with bad password.
        '''
        dut = self.duts[0]
        with self.assertRaises(CvpLoginError):
            self.clnt.connect([dut['node']], dut['username'], 'password')

    def test_connect_node_bad(self):
        ''' Verify connection fails to a single bogus CVP node
        '''
        with self.assertRaises(CvpLoginError):
            self.clnt.connect(['bogus'], 'username', 'password',
                              connect_timeout=1)

    def test_connect_non_cvp_node(self):
        ''' Verify connection fails to a non-CVP node
        '''
        with self.assertRaises(CvpLoginError):
            self.clnt.connect(['localhost'], 'username', 'password')

    def test_connect_all_nodes_bad(self):
        ''' Verify connection fails to a single bogus CVP node
        '''
        with self.assertRaises(CvpLoginError):
            self.clnt.connect(['bogus1', 'bogus2', 'bogus3'], 'username',
                              'password', connect_timeout=1)

    def test_connect_n1_bad_n2_good(self):
        ''' Verify connect succeeds even if one node is bad
        '''
        dut = self.duts[0]
        self.clnt.connect(['bogus', dut['node']], dut['username'],
                          dut['password'], connect_timeout=2)

    def test_connect_nodes_arg_bad(self):
        ''' Verify non-list nodes argument raises a TypeError
        '''
        with self.assertRaises(TypeError):
            self.clnt.connect('bogus', 'username', 'password')

    def test_connect_port_bad(self):
        ''' Verify non-http protocol with default port raises a TypeError
        '''
        dut = self.duts[0]
        with self.assertRaises(ValueError):
            self.clnt.connect([dut['node']], dut['username'], dut['password'],
                              protocol='bogus')

    def test_get_not_connected(self):
        ''' Verify get with no connection raises a ValueError
        '''
        with self.assertRaises(ValueError):
            self.clnt.get('/bogus')

    def test_get(self):
        ''' Verify get of CVP info
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        self.assertIn('version', result)

    def test_get_recover_session(self):
        ''' Verify client(get) recovers session after logout
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        self.assertIn('version', result)

    def test_get_recover_session_bg(self):
        ''' Verify client(get) recovers session after logout for bad/good node
        '''
        dut = self.duts[0]
        self.clnt.connect(['bogus', dut['node']], dut['username'],
                          dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        self.assertIn('version', result)

    def test_get_cvp_error(self):
        ''' Verify get of bad CVP request returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(CvpRequestError):
            self.clnt.get('/aaa/getServerById.do')

    def test_get_cvp_url_bad(self):
        ''' Verify get with bad URL returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(CvpApiError):
            self.clnt.get('/aaa/bogus.do')

    def test_get_handle_timeout(self):
        ''' Verify get with bad URL returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(Timeout):
            self.clnt.get('/tasks/getTasks.do', timeout=0.0001)

    def test_get_except_fail_reconnect(self):
        ''' Verify exception raised if session fails and cannot be
            re-established.
        '''
        dut = self.duts[0]
        nodes = ['bogus', dut['node']]
        self.clnt.connect(nodes, dut['username'], dut['password'])
        # Change the password for the CVP user so that a session reconnect
        # to any node will fail
        self._change_passwd(nodes, dut['username'], dut['password'],
                            self.NEW_PASSWORD)

        try:
            # Logout to end the current session and force a reconnect for the
            # next request.
            result = self.clnt.post('/login/logout.do', None)
            self.assertIn('data', result)
            self.assertEqual('success', result['data'])

        except Exception as error:
            # Should not have had an exception. Restore the CVP password
            # and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        try:
            # Try a get request and expect a CvpSessionLogOutError
            result = self.clnt.get('/cvpInfo/getCvpInfo.do')
        except CvpSessionLogOutError as error:
            pass
        except Exception as error:
            # Unexpected error, restore password and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        # Restore password
        self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                            dut['password'])

    def test_post_not_connected(self):
        ''' Verify post with no connection raises a ValueError
        '''
        with self.assertRaises(ValueError):
            self.clnt.post('/bogus', None)

    def test_post(self):
        ''' Verify post of CVP info
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])

    def test_post_recover_session(self):
        ''' Verify client(post) recovers session after logout
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertEqual('success', result['data'])

    def test_post_recover_session_bg(self):
        ''' Verify client(post) recovers session after logout for bad/good node
        '''
        dut = self.duts[0]
        self.clnt.connect(['bogus', dut['node']], dut['username'],
                          dut['password'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertIn('data', result)
        self.assertEqual('success', result['data'])
        result = self.clnt.post('/login/logout.do', None)
        self.assertEqual('success', result['data'])

    def test_post_cvp_bad_schema(self):
        ''' Verify post with bad schema returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(CvpApiError):
            self.clnt.post('/aaa/saveAAADetails.do', None)

    def test_post_cvp_url_bad(self):
        ''' Verify post with bad URL returns an error
        '''
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        with self.assertRaises(CvpApiError):
            self.clnt.post('/aaa/bogus.do', None)

    def test_post_except_fail_reconn(self):
        ''' Verify exception raised if session fails and cannot be
            re-established.
        '''
        dut = self.duts[0]
        nodes = ['bogus', dut['node']]
        self.clnt.connect(nodes, dut['username'], dut['password'])
        # Change the password for the CVP user so that a session reconnect
        # to any node will fail
        self._change_passwd(nodes, dut['username'], dut['password'],
                            self.NEW_PASSWORD)

        try:
            # Logout to end the current session and force a reconnect for the
            # next request.
            result = self.clnt.post('/login/logout.do', None)
            self.assertIn('data', result)
            self.assertEqual('success', result['data'])

        except Exception as error:
            # Should not have had an exception. Restore the CVP password
            # and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        try:
            # Try a post request and expect a CvpSessionLogOutError
            result = self.clnt.post('/login/logout.do', None)
        except CvpSessionLogOutError as error:
            pass
        except Exception as error:
            # Unexpected error, restore password and re-raise the error.
            self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                                dut['password'])
            raise error
        # Restore password
        self._change_passwd(nodes, dut['username'], self.NEW_PASSWORD,
                            dut['password'])
Ejemplo n.º 11
0
# Copyright (c) 2021 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the COPYING file.

from cvprac.cvp_client import CvpClient
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

# Create connection to CloudVision
clnt = CvpClient()
clnt.connect(nodes=['cvp1'], username="******", password="******")

configletName = "cvprac_example"

configlet = """!
interface Ethernet10
   description test
   ip address 10.144.144.1/24
!
"""

clnt.api.add_configlet(configletName, configlet)
Ejemplo n.º 12
0
# Use of this source code is governed by the Apache License 2.0
# that can be found in the COPYING file.

from cvprac.cvp_client import CvpClient
from cvprac.cvp_client_errors import CvpApiError
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
from cvprac.cvp_client import CvpClient

# Create connection to CloudVision using Service Account token
with open("cvaas.tok") as f:
    token = f.read().strip('\n')

clnt = CvpClient()
clnt.connect(nodes=['www.arista.io'],
             username='',
             password='',
             is_cvaas=True,
             api_token=token)

username = "******"
password = ""
role = "network-admin"
status = "Enabled"
first_name = "John"
last_name = "Smith"
email = "*****@*****.**"
utype = "SSO"
Ejemplo n.º 13
0
class TestClient(unittest.TestCase):
    """ Unit test cases for CvpClient
    """
    # pylint: disable=protected-access
    # pylint: disable=invalid-name

    def setUp(self):
        """ Setup for CvpClient unittests
        """
        self.clnt = CvpClient()
        nodes = ['1.1.1.1']
        self.clnt.nodes = nodes
        self.clnt.node_cnt = len(nodes)
        self.clnt.node_pool = cycle(nodes)

    def test_create_session_default_https(self):
        """ Test connection to CVP nodes will default to https.
        """
        url = 'https://1.1.1.1:443/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.return_value = None
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)

    def test_create_session_https_port(self):
        """ Test https session with user provided port.
        """
        self.clnt.port = 7777
        url = 'https://1.1.1.1:7777/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.return_value = None
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)

    def test_create_session_http_fallback(self):
        """ Test a failed https connection will attempt to fallback to http.
        """
        self.clnt.port = None
        url = 'http://1.1.1.1:80/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.side_effect = ['Failed to connect via https',
                                                None]
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)
        self.assertEqual(self.clnt.error_msg, '\n')

    def test_create_session_http_fallback_port(self):
        """ Test http fallback will use a user provided port number.
        """
        self.clnt.port = 8888
        url = 'http://1.1.1.1:8888/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.side_effect = ['Failed to connect via https',
                                                None]
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)
        self.assertEqual(self.clnt.error_msg, '\n')

    def test_create_session_no_http_fallback_with_cert(self):
        """ If user passes a certificate to CvpClient it will only attempt to
            use https and not fall back to http.
        """
        self.clnt.port = None
        self.clnt.cert = 'cert'
        url = 'https://1.1.1.1:443/web'
        error = '\n1.1.1.1: Failed to connect via https\n'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.return_value = 'Failed to connect via https'
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)
        self.assertEqual(self.clnt.error_msg, error)

    def test_make_request_good(self):
        """ Test request does not raise exception and returns json.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        request_return_value = Mock()
        self.clnt.session.get.return_value = request_return_value
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        request_return_value.json.assert_called_once_with()
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_timeout(self):
        """ Test request timeout exception raised if hit on multiple nodes.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.side_effect = ReadTimeout('Timeout')
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 3
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 3
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(ReadTimeout):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_http_error(self):
        """ Test request http exception raised if hit on multiple nodes.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.side_effect = HTTPError('HTTPError')
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(HTTPError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_no_session_error(self):
        """ Test request exception raised if hit on multiple nodes and
            _create_session fails to reset clnt.session.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.side_effect = HTTPError('HTTPError')
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 0.01
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(HTTPError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_response_error(self):
        """ Test request exception raised from CVP response data.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.return_value = Mock()
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock()
        self.clnt._is_good_response.side_effect = CvpApiError('CvpApiError')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(CvpApiError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_response_error_unauthorized(self):
        """ Test request exception raised if CVP responds unauthorized user.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.return_value = Mock()
        self.clnt._create_session = Mock()
        self.clnt._reset_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock()
        self.clnt._is_good_response.side_effect = CvpApiError(
            msg='Unauthorized User')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(CvpApiError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_response_error_logout(self):
        """ Test request exception raised if CVP logout error hit.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.return_value = Mock()
        self.clnt._create_session = Mock()
        self.clnt._reset_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock()
        self.clnt._is_good_response.side_effect = CvpSessionLogOutError('bad')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(CvpSessionLogOutError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')
Ejemplo n.º 14
0
# Copyright (c) 2020 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the COPYING file.

from cvprac.cvp_client import CvpClient
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

# Create connection to CloudVision
clnt = CvpClient()
clnt.connect(['cvp1'],'username', 'password')

image_name = "vEOS-4.26.0.1F"
image = clnt.api.get_image_bundle_by_name(image_name)

container_name = "TP_FABRIC"
container = clnt.api.get_container_by_name(container_name)

clnt.api.remove_image_from_container(image, container)
Ejemplo n.º 15
0
from cvprac.cvp_client import CvpClient
from pprint import pprint
import json
import sys
from jinja2 import Environment, FileSystemLoader
import itertools

robotlist = []
countlist = []

client = CvpClient()
client.connect(['10.20.30.142'], 'daniel', 'daniel123')
inventory = client.api.get_inventory()


def initcvpyaml():
    sys.stdout = open('cvp.yaml', 'w')
    print '---'
    print 'TRANSPORT: https'
    print 'PORT: 443'
    print 'USERNAME: daniel'
    print 'PASSWORD: daniel123'
    print '   '
    print 'RUNFORMAT: suite'
    print '   '
    print 'PROD_TAGS:'
    print '  - ignoretags'
    print '   '
    print 'testfiles:'
    print '  - network_validation'
    print '   '
Ejemplo n.º 16
0
from pprint import pprint
from cvprac.cvp_client import CvpClient
from cvprac.cvp_api import CvpApi
import urllib3
import requests

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning
                         )  # This will disable invalid cert warnings

client = CvpClient()
api = CvpApi(client)

client.connect(['cvp.lab.local'], 'jpatterson', 'P3pp3r101!')

result = client.get('/cvpInfo/getCvpInfo.do')

newresult = client.get(
    'https://cvp.lab.local/cvpservice/image/getImages.do?startIndex=0&endIndex=0'
)

print newresult

# test1 = clnt.get('/cvpservice/snapshot/getSnapshots.do?startIndex=0&endIndex=0')

print result
Ejemplo n.º 17
0
def main():
    clnt = CvpClient()
    clnt.connect(['192.168.130.3'], 'cvpadmin', 'mypass', protocol='https')

    logs = get_logs(clnt)
    print json.dumps(logs, indent=4, sort_keys=True)
Ejemplo n.º 18
0
class TestCvpClient(DutSystemTest):
    ''' Test cases for the CvpClient class.
    '''
    # pylint: disable=too-many-public-methods
    # pylint: disable=invalid-name
    def setUp(self):
        ''' Instantiate the CvpClient class and connect to the CVP node.
            Log messages to the /tmp/TestCvpClient.log
        '''
        super(TestCvpClient, self).setUp()
        self.clnt = CvpClient(filename='/tmp/TestCvpClient.log')
        self.assertIsNotNone(self.clnt)
        self.assertIsNone(self.clnt.last_used_node)
        dut = self.duts[0]
        cert = False
        if 'cert' in dut:
            cert = dut['cert']
        self.clnt.connect([dut['node']], dut['username'], dut['password'], 10,
                          cert=cert)
        self.api = self.clnt.api
        self.assertIsNotNone(self.api)

        # Verify that there is at least one device in the inventory
        err_msg = 'CVP node must contain at least one device'
        result = self.api.get_inventory()
        self.assertIsNotNone(result)
        self.assertGreaterEqual(len(result), 1, msg=err_msg)
        self.device = result[0]

        # Get the container for the device on the list and
        # use that container as the parent container.
        result = self.api.search_topology(self.device['fqdn'])
        self.assertIsNotNone(result)
        dev_container = result['netElementContainerList']
        self.assertGreaterEqual(len(dev_container), 1)
        info = dev_container[0]
        result = self.api.search_topology(info['containerName'])
        self.assertIsNotNone(result)
        self.container = result['containerList'][0]

        # Get the configlets assigned to the device.  There must be at least 1.
        err_msg = 'CVP node device must have at least one configlet assigned'
        key = info['netElementKey']
        result = self.api.get_configlets_by_device_id(key)
        self.assertGreaterEqual(len(result), 1, msg=err_msg)
        self.dev_configlets = result

    def tearDown(self):
        ''' Destroy the CvpClient class.
        '''
        super(TestCvpClient, self).tearDown()
        self.api = None
        self.clnt = None

    def _get_next_task_id(self):
        ''' Return the next task id.

            Returns:
                task_id (str): Task ID
        '''
        # Get all the tasks and the task id of the next task created is
        # the length + 1.
        results = self.api.get_tasks()
        self.assertIsNotNone(results)
        return str(int(results['total']) + 1)

    def _create_task(self):
        ''' Create a task by making a simple change to a configlet assigned
            to the device.

            Returns:
                (task_id, config)
                task_id (str): Task ID
                config (str): Previous configlets contents
        '''
        task_id = self._get_next_task_id()

        # Update the lldp time in the first configlet in the list.
        configlet = None
        for conf in self.dev_configlets:
            if conf['netElementCount'] == 1:
                configlet = conf
                break
        if configlet is None:
            configlet = self.dev_configlets[0]

        config = configlet['config']
        org_config = config

        match = re.match(r'lldp timer (\d+)', config)
        if match is not None:
            value = int(match.group(1)) + 1
            repl = 'lldp timer %d' % value
            config = re.sub(match.group(0), repl, config)
        else:
            value = 13
            config = ('lldp timer %d\n' % value) + config
        configlet['config'] = config

        # Updating the configlet will cause a task to be created to apply
        # the change to the device.
        self.api.update_configlet(config, configlet['key'], configlet['name'])

        # Wait 30 seconds for task to get created
        cnt = 30
        if self.clnt.apiversion is None:
            self.api.get_cvp_info()
        if self.clnt.apiversion == 'v2':
            # Increase timeout by 30 sec for CVP 2018.2 and beyond
            cnt += 30
        while cnt > 0:
            time.sleep(1)
            result = self.api.get_task_by_id(task_id)
            if result is not None:
                break
            cnt -= 1
        err_msg = 'Timeout waiting for task id %s to be created' % task_id
        self.assertGreater(cnt, 0, msg=err_msg)

        return task_id, org_config

    def test_api_get_cvp_info(self):
        ''' Verify get_cvp_info and verify setting of client last_used_node
            parameter
        '''
        result = self.api.get_cvp_info()
        self.assertIsNotNone(result)
        self.assertIn('version', result)
        self.assertIn(self.clnt.last_used_node, self.clnt.url_prefix)
        self.assertEqual(self.clnt.version, result['version'])
        self.assertIsNotNone(self.clnt.apiversion)

    def test_api_check_compliance(self):
        ''' Verify check_compliance
        '''
        key = self.device['key']
        ntype = self.device['type']
        result = self.api.check_compliance(key, ntype)
        self.assertEqual(result['complianceCode'], '0000')
        self.assertEqual(result['complianceIndication'], 'NONE')

    def test_api_task_operations(self):
        ''' Verify get_task_by_id, get_task_by_status, add_note_to_task,
             get_logs_by_id, and cancel_task
        '''
        (task_id, org_config) = self._create_task()

        # Test get_task_by_id
        result = self.api.get_task_by_id(task_id)
        self.assertIsNotNone(result)
        self.assertEqual(result['workOrderId'], task_id)

        # Test get_task_by_status
        results = self.api.get_tasks_by_status('PENDING')
        # More than one task may be returned.
        found = False
        for result in results:
            actual_task_id = result['workOrderId']
            if actual_task_id == task_id:
                found = True
                break
        err_msg = 'Task id: %s not in list of PENDING tasks' % task_id
        self.assertTrue(found, msg=err_msg)

        # Test add_note_to_task
        note = 'Test Generated'
        self.api.add_note_to_task(task_id, note)

        # Verify task operations
        result = self.api.get_task_by_id(task_id)
        self.assertIsNotNone(result)
        self.assertEqual(result['note'], note)
        self.assertEqual(result['workOrderUserDefinedStatus'], 'Pending')

        result = self.api.check_compliance(self.device['key'],
                                           self.device['type'])
        self.assertEqual(result['complianceCode'], '0001')

        # Test cancel_task
        self.api.cancel_task(task_id)
        time.sleep(1)
        result = self.api.get_task_by_id(task_id)
        self.assertIsNotNone(result)
        self.assertEqual(result['workOrderUserDefinedStatus'], 'Cancelled')

        result = self.api.check_compliance(self.device['key'],
                                           self.device['type'])
        self.assertEqual(result['complianceCode'], '0001')

        # Get the task logs
        result = self.api.get_logs_by_id(task_id)
        self.assertIsNotNone(result)

        result = self.api.check_compliance(self.device['key'],
                                           self.device['type'])
        self.assertEqual(result['complianceCode'], '0001')

        # Restore the configlet to what it was before the task was created.
        task_id = self._get_next_task_id()
        configlet = None
        for conf in self.dev_configlets:
            if conf['netElementCount'] == 1:
                configlet = conf
                break
        if configlet is None:
            configlet = self.dev_configlets[0]
        self.api.update_configlet(org_config, configlet['key'],
                                  configlet['name'])
        time.sleep(2)
        # Cancel task
        self.api.cancel_task(task_id)

        # Check compliance
        self.test_api_check_compliance()

    def test_api_validate_config(self):
        ''' Verify valid config returns True
        '''
        config = 'interface ethernet1\n description test'
        result = self.api.validate_config(self.device['key'], config)
        self.assertEqual(result, True)

    def test_api_validate_config_error(self):
        ''' Verify an invalid config returns False
        '''
        config = 'interface ethernet1\n typocommand test'
        result = self.api.validate_config(self.device['key'], config)
        self.assertEqual(result, False)

    def test_api_get_task_by_id_bad(self):
        ''' Verify get_task_by_id with bad task id
        '''
        result = self.api.get_task_by_id(10000000)
        self.assertIsNone(result)

    def test_api_get_task_by_id_fmt_bad(self):
        ''' Verify get_task_by_id with bad task id
        '''
        result = self.api.get_task_by_id('BOGUS')
        self.assertIsNone(result)

    def test_api_get_tasks_by_s_bad(self):
        ''' Verify get_tasks_by_status
        '''
        result = self.api.get_tasks_by_status('BOGUS')
        self.assertIsNotNone(result)

    def test_api_get_configlets(self):
        ''' Verify get_configlets
        '''
        result = self.api.get_configlets()

        # Format the configlet lists into name keyed dictionaries
        dev_cfglts = {}
        for cfglt in self.dev_configlets:
            dev_cfglts.update({cfglt['name']: cfglt})

        rslt_cfglts = {}
        for cfglt in result['data']:
            rslt_cfglts.update({cfglt['name']: cfglt})

        # Make sure the device configlets are all returned by the
        # get_configlets call
        for cfglt_name in dev_cfglts:
            self.assertIn(cfglt_name, rslt_cfglts)
            self.assertDictEqual(dev_cfglts[cfglt_name],
                                 rslt_cfglts[cfglt_name])

    def test_api_get_configlet_builder(self):
        ''' Verify get_configlet_builder
        '''
        cfglt = self.api.get_configlet_by_name('SYS_TelemetryBuilderV2')
        result = self.api.get_configlet_builder(cfglt['key'])

        # Verify the following keys and types are
        # returned by the request
        exp_data = {
            u'isAssigned': bool,
            u'name': (unicode, str),
            u'formList': list,
            u'main_script': dict,
        }
        for key in exp_data:
            self.assertIn(key, result['data'])
            self.assertIsInstance(result['data'][key], exp_data[key])

    def test_api_get_configlet_by_name(self):
        ''' Verify get_configlet_by_name
        '''
        configlet = None
        for conf in self.dev_configlets:
            if conf['netElementCount'] == 1:
                configlet = conf
                break
        if configlet is None:
            configlet = self.dev_configlets[0]
        result = self.api.get_configlet_by_name(configlet['name'])
        self.assertIsNotNone(result)
        self.assertEqual(result['key'], configlet['key'])

    def test_api_get_configlets_by_container_id(self):
        ''' Verify get_configlets_by_container_id
        '''
        result = self.api.get_configlets_by_container_id(
            self.container['key']
        )

        # Verify the following keys and types are returned by the request
        exp_data = {
            'configletList': list,
            'configletMapper': dict,
            'total': int,
        }
        self.assertListEqual(exp_data.keys(), result.keys())
        for key in exp_data:
            self.assertIsInstance(result[key], exp_data[key])

    def test_api_get_configlets_by_netelement_id(self):
        ''' Verify get_configlets_by_netelement_id
        '''
        result = self.api.get_configlets_by_netelement_id(
            self.device['key']
        )

        # Verify the following keys and types are returned by the request
        exp_data = {
            'configletList': list,
            'configletMapper': dict,
            'total': int,
        }
        self.assertListEqual(exp_data.keys(), result.keys())
        for key in exp_data:
            self.assertIsInstance(result[key], exp_data[key])

    def test_api_get_applied_devices(self):
        ''' Verify get_applied_devices
        '''
        for cfglt in self.dev_configlets:
            result = self.api.get_applied_devices(cfglt['name'])

            # Verify the following keys and types are
            # returned by the request
            exp_data = {
                'data': list,
                'total': int,
            }
            self.assertListEqual(exp_data.keys(), result.keys())
            for key in exp_data:
                self.assertIsInstance(result[key], exp_data[key])

    def test_api_get_applied_containers(self):
        ''' Verify get_applied_containers
        '''
        for cfglt in self.dev_configlets:
            result = self.api.get_applied_containers(cfglt['name'])

            # Verify the following keys and types are
            # returned by the request
            exp_data = {
                'data': list,
                'total': int,
            }
            self.assertListEqual(exp_data.keys(), result.keys())
            for key in exp_data:
                self.assertIsInstance(result[key], exp_data[key])

    def test_api_get_configlet_history(self):
        ''' Verify get_configlet_history
        '''
        key = None
        for conf in self.dev_configlets:
            if conf['netElementCount'] == 1:
                key = conf['key']
                break
        if key is None:
            key = self.dev_configlets[0]['key']
        result = self.api.get_configlet_history(key)
        self.assertIsNotNone(result)

    def test_api_get_device_by_name(self):
        ''' Verify get_device_by_name
        '''
        result = self.api.get_device_by_name(self.device['fqdn'])
        self.assertIsNotNone(result)
        self.assertEqual(result, self.device)

    def test_api_get_device_configuration(self):
        ''' Verify get_device_configuration
        '''
        result = self.api.get_device_configuration(self.device['key'])
        self.assertIsNotNone(result)
        config_lines = result.splitlines()
        for line in config_lines:
            if 'hostname' in line:
                self.assertEqual(line, 'hostname %s' % self.device['fqdn'])

    def test_api_get_device_by_name_bad(self):
        ''' Verify get_device_by_name with bad fqdn
        '''
        result = self.api.get_device_by_name('bogus_host_name')
        self.assertIsNotNone(result)
        self.assertEqual(result, {})

    def test_api_get_device_by_name_substring(self):
        ''' Verify get_device_by_name with partial fqdn returns nothing
        '''
        result = self.api.get_device_by_name(self.device['fqdn'][1:])
        self.assertIsNotNone(result)
        self.assertEqual(result, {})

    def _create_configlet(self, name, config):
        # Delete the configlet in case it was left by previous test run
        try:
            result = self.api.get_configlet_by_name(name)
            self.api.delete_configlet(name, result['key'])
        except CvpApiError:
            pass

        # Add the configlet
        key = self.api.add_configlet(name, config)
        self.assertIsNotNone(key)
        return key

    def test_api_add_delete_configlet(self):
        ''' Verify add_configlet and delete_configlet
        '''
        name = 'test_configlet'
        config = 'lldp timer 9'

        # Add the configlet
        key = self._create_configlet(name, config)

        # Verify configlet was added
        result = self.api.get_configlet_by_name(name)
        self.assertIsNotNone(result)
        self.assertEqual(result['name'], name)
        self.assertEqual(result['config'], config)
        self.assertEqual(result['key'], key)

        # Delete the configlet
        self.api.delete_configlet(name, key)

        # Verify configlet was deleted
        with self.assertRaises(CvpApiError):
            self.api.get_configlet_by_name(name)

    def test_api_add_note_to_configlet(self):
        ''' Verify add_note_to_configlet
        '''
        name = 'test_configlet_with_note_%d' % time.time()
        config = 'lldp timer 9'

        # Add the configlet
        key = self._create_configlet(name, config)

        # Add a note to the configlet
        note = 'Updated by cvprac test'
        result = self.api.add_note_to_configlet(key, note)

        # Verify note was added to configlet
        result = self.api.get_configlet_by_name(name)
        self.assertIsNotNone(result)
        self.assertEqual(result['name'], name)
        self.assertEqual(result['config'], config)
        self.assertEqual(result['key'], key)
        self.assertEqual(result['note'], note)

    def _execute_task(self, task_id):
        ''' Execute a task and wait for it to complete.
        '''
        # Test add_note_to_task
        self.api.add_note_to_task(task_id, 'Test Generated')

        self.api.execute_task(task_id)

        # Verify task executed within 30 seconds
        cnt = 30
        while cnt > 0:
            time.sleep(1)
            result = self.api.get_task_by_id(task_id)
            status = result['workOrderUserDefinedStatus']
            if status == 'Completed' or status == 'Failed':
                break
            cnt -= 1
        err_msg = 'Execution for task id %s failed' % task_id
        self.assertNotEqual(status, 'Failed', msg=err_msg)
        err_msg = 'Timeout waiting for task id %s to execute' % task_id
        self.assertGreater(cnt, 0, msg=err_msg)

    def test_api_execute_task(self):
        ''' Verify execute_task
        '''
        # Create task and execute it
        (task_id, _) = self._create_task()
        self._execute_task(task_id)

        # Check compliance
        self.test_api_check_compliance()

    def test_api_get_containers(self):
        ''' Verify get containers
        '''
        result = self.api.get_containers()
        self.assertIsNotNone(result)
        total = result['total']
        self.assertEqual(len(result['data']), total)

    def test_api_no_container_by_name(self):
        ''' Verify searching for a container name that doesn't exist returns
            None
        '''
        container = self.api.get_container_by_name('NonExistentContainer')
        self.assertIsNone(container)

    def test_api_get_devices_in_container(self):
        ''' Verify searching for devices in a container returns only the
            devices under the given container name.
        '''
        # Get All Devices
        all_devices = self.api.get_inventory()

        # Grab key of container to test from first device in inventory
        device = all_devices[0]
        parent_cont = device['parentContainerId']

        # Make list of all devices from full inventory that are in the
        # same container as the first device
        devices_in_container = []
        for dev in all_devices:
            if dev['parentContainerId'] == parent_cont:
                devices_in_container.append(dev)

        # Get the name of the container for the container key from
        # the first device
        all_containers = self.api.get_containers()
        container_name = None
        for container in all_containers['data']:
            if container['key'] == parent_cont:
                container_name = container['name']

        result = self.api.get_devices_in_container(container_name)
        self.assertEqual(result, devices_in_container)

    def test_api_containers(self):
        ''' Verify add_container, get_container_by_name and delete_container
        '''
        name = 'CVPRACTEST'
        parent = self.container
        # Verify create container
        self.api.add_container(name, parent['name'], parent['key'])

        # Verify get container for exact container name returns only that
        # container
        container = self.api.get_container_by_name(name)
        self.assertIsNotNone(container)
        self.assertEqual(container['name'], name)

        # Verify finding created container using search topology
        result = self.api.search_topology(name)
        self.assertEqual(len(result['containerList']), 1)
        container = result['containerList'][0]
        self.assertEqual(container['name'], name)
        key = container['key']
        # Verify newly created container has no devices in it
        new_cont_devices = self.api.get_devices_in_container(name)
        self.assertEqual(new_cont_devices, [])

        # Verify move device to container
        device = self.api.get_inventory()[0]
        orig_cont = self.api.get_parent_container_for_device(
            device['key'])
        if orig_cont['key'] != 'undefined_container':
            task = self.api.move_device_to_container(
                'test', device, container)['data']['taskIds'][0]
            self.api.cancel_task(task)
            curr_cont = self.api.get_parent_container_for_device(device['key'])
            self.assertEqual(curr_cont['key'], key)
            device = self.api.get_device_by_name(device['fqdn'])
            if 'parentContainerId' in device:
                self.assertEqual(device['parentContainerId'], key)
            task = self.api.move_device_to_container(
                'test', device, orig_cont)['data']['taskIds'][0]
            self.api.cancel_task(task)
            curr_cont = self.api.get_parent_container_for_device(device['key'])
            self.assertEqual(curr_cont['key'], orig_cont['key'])
            device = self.api.get_device_by_name(device['fqdn'])
            if 'parentContainerId' in device:
                self.assertEqual(device['parentContainerId'], orig_cont['key'])

        # Verify delete container
        self.api.delete_container(name, key, parent['name'], parent['key'])
        result = self.api.search_topology(name)
        self.assertEqual(len(result['containerList']), 0)

    def test_api_container_url_encode_name(self):
        ''' Verify special characters can be used in container names
        '''
        new_cont_name = 'Rack2+_DC11'
        parent = self.container
        # Verify create container
        self.api.add_container(new_cont_name, parent['name'], parent['key'])
        # Verify get container for container with special characters in name
        container = self.api.get_container_by_name(new_cont_name)
        self.assertIsNotNone(container)
        self.assertEqual(container['name'], new_cont_name)
        # Verify delete container
        self.api.delete_container(new_cont_name, container['key'],
                                  parent['name'], parent['key'])
        result = self.api.search_topology(new_cont_name)
        self.assertEqual(len(result['containerList']), 0)

    def test_api_configlets_to_device(self):
        ''' Verify apply_configlets_to_device and remove_configlets_from_device
        '''
        # Create a new configlet
        name = 'test_configlet'
        config = 'alias srie show running-config interface ethernet 1'

        # Add the configlet
        key = self._create_configlet(name, config)

        # Get the next task ID
        task_id = self._get_next_task_id()

        # Apply the configlet to the device
        label = 'cvprac test'
        param = {'name': name, 'key': key}
        self.api.apply_configlets_to_device(label, self.device, [param])

        # Validate task was created to apply the configlet to device
        # Wait 30 seconds for task to get created
        cnt = 30
        while cnt > 0:
            time.sleep(1)
            result = self.api.get_task_by_id(task_id)
            if result is not None:
                break
            cnt -= 1
        self.assertIsNotNone(result)
        self.assertEqual(result['workOrderId'], task_id)
        self.assertIn(label, result['description'])

        # Execute Task
        self._execute_task(task_id)

        # Get the next task ID
        task_id = self._get_next_task_id()

        # Remove configlet from device
        self.api.remove_configlets_from_device(label, self.device, [param])

        # Validate task was created to remove the configlet to device
        # Wait 30 seconds for task to get created
        cnt = 30
        while cnt > 0:
            time.sleep(1)
            result = self.api.get_task_by_id(task_id)
            if result is not None:
                break
            cnt -= 1
        self.assertIsNotNone(result)
        self.assertEqual(result['workOrderId'], task_id)
        self.assertIn(label, result['description'])

        # Execute Task
        self._execute_task(task_id)

        # Delete the configlet
        self.api.delete_configlet(name, key)

        # Check compliance
        self.test_api_check_compliance()

    def test_api_request_timeout(self):
        ''' Verify api timeout
        '''
        self.assertEqual(self.api.request_timeout, 30)
        self.api.request_timeout = 0.0001
        with self.assertRaises(Timeout):
            self.api.get_cvp_info()
        self.api.request_timeout = 30.0

    def test_api_get_all_temp_actions(self):
        ''' Verify get_all_temp_actions
        '''
        # pylint: disable=protected-access
        name = 'test_configlet'
        config = 'lldp timer 9'

        # Add a configlet
        key = self._create_configlet(name, config)

        # Apply the configlet to the container
        data = {
            'data': [{
                'info': 'test_api_get_all_temp_actions',
                'infoPreview': 'test_api_get_all_temp_actions',
                'action': 'associate',
                'nodeType': 'configlet',
                'nodeId': '',
                'toId': self.container['key'],
                'fromId': '',
                'nodeName': '',
                'fromName': '',
                'toName': self.container['name'],
                'toIdType': 'container',
                'configletList': [key],
                'configletNamesList': [name],
                'ignoreConfigletList': [],
                'ignoreConfigletNamesList': [],
                'configletBuilderList' : [],
                'configletBuilderNamesList' : [],
                'ignoreConfigletBuilderList' : [],
                'ignoreConfigletBuilderNamesList': [],
            }]
        }
        self.api._add_temp_action(data)

        # Request the list of temp actions
        result = self.api.get_all_temp_actions()

        # Delete the temporary action and the configlet
        self.clnt.post('//provisioning/deleteAllTempAction.do')
        self.api.delete_configlet(name, key)

        # Validate the results
        # There should be 1 temp action
        self.assertEqual(result['total'], 1)
        # The temp action should contain the data from the add action
        for dkey in data['data'][0]:
            self.assertIn(dkey, result['data'][0].keys())
            self.assertEqual(data['data'][0][dkey], result['data'][0][dkey])

    def test_api_get_event_by_id_bad(self):
        ''' Verify get_event_by_id returns an error for a bad ID
        '''
        try:
            # The api request should fail
            result = self.api.get_event_by_id('\n*')
            self.assertIsNone(result)
        except CvpApiError as ebi_err:
            # The error should contain 'Invalid Event Id'
            self.assertIn('Invalid Event Id', str(ebi_err))

    def test_api_get_default_snapshot_template(self):
        ''' Verify get_default_snapshot_template.
        '''
        result = self.api.get_default_snapshot_template()
        if result is not None:
            expected = {
                u'ccTasksTagged': 0,
                u'classId': 63,
                u'commandCount': 1,
                u'createdBy': u'System',
                u'default': True,
                u'factoryId': 1,
                u'id': 63,
                u'isDefault': True,
                u'key': u'Initial_Template',
                u'name': u'Show_Inventory',
                u'note': u'',
            }

            # Remove the snapshotCount, totalSnapshotCount and
            # createdTimestamp, since these can change with usage
            result.pop('snapshotCount', None)
            result.pop('totalSnapshotCount', None)
            result.pop('createdTimestamp', None)
            self.assertDictEqual(result, expected)

    def test_api_capture_container_level_snapshot(self):
        ''' Verify capture_container_level_snapshot
        '''
        # Get the container and snapshot keys
        container_key = self.container['key']
        default_snap = self.api.get_default_snapshot_template()
        if default_snap is not None:
            snapshot_key = default_snap['key']

            # Initialize the snapshot event
            result = self.api.capture_container_level_snapshot(
                snapshot_key, container_key)
            self.assertIn('data', result)
            self.assertIn('eventId', result)
            self.assertEqual('success', result['data'])

    def test_api_add_image(self):
        ''' Verify add_image
        '''
        # Copy the test image file with a timestamp appended
        image_file = 'test/fixtures/image-file-%s.swix' % time.time()
        shutil.copyfile('test/fixtures/image-file.swix', image_file)

        # Upload the image to the cluster
        result = self.api.add_image(image_file)

        # Remove the timestamp copy from the local filesystem
        os.remove(image_file)

        self.assertNotIn('errorCode', result)
        self.assertIn('result', result)
        self.assertEqual(result['result'], 'success')

    def test_api_get_images(self):
        ''' Verify get images
        '''
        result = self.api.get_images()
        self.assertIsNotNone(result)
        self.assertEqual(result['total'], len(result['data']))

    def test_api_get_image_bundles(self):
        ''' Verify get image bundles
        '''
        result = self.api.get_image_bundles()
        self.assertIsNotNone(result)
        self.assertEqual(result['total'], len(result['data']))

    def test_api_save_update_image_bundle(self):
        ''' Verify save_image_bundle and update_image_bundle
        '''
        # Get an existing bundle
        bundles = self.api.get_image_bundles()
        bundle = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])

        # Get the list of images from the existing bundle
        images = bundle['images']
        # Remove the unused keys from the images
        remove_keys = ['appliedContainersCount', 'appliedDevicesCount',
                       'factoryId', 'id', 'imageFile', 'imageFileName',
                       'isHotFix', 'uploadedDateinLongFormat', 'user']
        for image in images:
            for key in remove_keys:
                image.pop(key, None)

        # Create a new bundle with the same images
        original_name = 'test_image_bundle_%d' % time.time()
        result = self.api.save_image_bundle(original_name, images)
        expected = r'Bundle\s*:\s+%s successfully created' % original_name
        self.assertRegexpMatches(result['data'], expected)

        # Get the bundle ID from the new bundle
        bundle = self.api.get_image_bundle_by_name(original_name)
        bundle_id = bundle['id']

        # Update the name of the bundle and mark it as uncertified
        updated_name = original_name + "_updated"
        result = self.api.update_image_bundle(bundle_id, updated_name, images,
                                              certified=False)
        expected = 'Image bundle updated successfully'
        self.assertRegexpMatches(result['data'], expected)

        # Verify the updated bundle name has the correct bundle ID
        # and is not a certified image bundle
        bundle = self.api.get_image_bundle_by_name(updated_name)
        self.assertEqual(bundle['id'], bundle_id)
        self.assertEqual(bundle['isCertifiedImage'], 'false')

        # Verify the original bundle name does not exist
        bundle = self.api.get_image_bundle_by_name(original_name)
        self.assertIsNone(bundle)

    def test_api_get_image_bundle_by_name(self):
        ''' Verify get image bundle by name
        '''
        bundles = self.api.get_image_bundles()
        if bundles['total'] > 0:
            bundle_name = bundles['data'][0]['name']
            bundle = self.api.get_image_bundle_by_name(bundle_name)
            self.assertEqual(bundle['name'], bundle_name)

    def test_api_get_image_bundle_by_name_doesnt_exist(self):
        ''' Verify get image bundle by name returns none if image bundle doesn't exist
        '''
        result = self.api.get_image_bundle_by_name('nonexistantimagebundle')
        self.assertIsNone(result)

    def test_api_apply_remove_image_device(self):
        ''' Verify task gets created when applying an image bundle to a device.
            This test only runs if at least one image bundle and one device
            exist in the CVP instance being used for testing.
        '''
        bundles = self.api.get_image_bundles()
        devices = self.api.get_inventory()
        # Verify at least one image bundle and device exist
        if bundles['total'] > 0 and len(devices) > 0:
            # Get device and image bundle
            b = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])
            d = self.api.get_device_by_name(devices[0]['fqdn'])
            applied_devices_count = b['appliedDevicesCount']

            # Apply image and verify at least one task id was created
            result = self.api.apply_image_to_device(b, d)
            self.assertIsNotNone(result)
            self.assertEqual(result['data']['status'], 'success')
            taskids = result['data']['taskIds']
            self.assertIsNotNone(taskids)

            # Verify image bundle has been applied to one additional device
            b = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])
            self.assertEqual((applied_devices_count + 1),
                             b['appliedDevicesCount'])

            # Verify task was created and in pending state
            task = self.api.get_task_by_id(taskids[0])
            self.assertIsNotNone(task)
            self.assertEqual(task['workOrderUserDefinedStatus'], 'Pending')

            # Cancel task and verify it is cancelled
            self.api.cancel_task(taskids[0])
            time.sleep(1)
            task = self.api.get_task_by_id(taskids[0])
            self.assertIsNotNone(task)
            self.assertEqual(task['workOrderUserDefinedStatus'], 'Cancelled')

            # Un-apply image bundle from device
            result = self.api.remove_image_from_device(b, d)
            self.assertIsNotNone(result)
            self.assertEqual(result['data']['status'], 'success')
            taskids = result['data']['taskIds']
            self.assertIsNotNone(taskids)

            # Verify image bundle applied to one less device
            b = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])
            self.assertEqual(applied_devices_count, b['appliedDevicesCount'])

    def test_api_apply_remove_image_container(self):
        ''' Verify image bundle is applied to container and removed.
            Test only runs if at least one image bundle exists. Test creates
            a container to apply bundle then removes the container at the end.
        '''
        bundles = self.api.get_image_bundles()
        if bundles['total'] > 0:
            # Create container, get container info, get bundle info
            name = 'imagecontainer'
            parent = self.container
            self.api.add_container(name, parent['name'], parent['key'])
            c = self.api.get_container_by_name(name)
            b = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])
            applied_container_count = b['appliedContainersCount']

            # Apply bundle to new container
            result = self.api.apply_image_to_container(b, c)
            self.assertIsNotNone(result)
            b = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])
            self.assertEqual(b['appliedContainersCount'],
                             (applied_container_count + 1))

            # Remove bundle from container
            result = self.api.remove_image_from_container(b, c)
            self.assertIsNotNone(result)
            b = self.api.get_image_bundle_by_name(bundles['data'][0]['name'])
            self.assertEqual(b['appliedContainersCount'],
                             applied_container_count)

            # Remove container
            self.api.delete_container(name, c['key'], parent['name'],
                                      parent['key'])

    def test_api_inventory(self):
        ''' Verify add_device_to_inventory and delete_device(s)
        '''
        # Get a device
        full_inv = self.api.get_inventory()
        device = full_inv[0]
        # Record number of current/original non connected devices
        orig_non_connect_count = self.api.get_non_connected_device_count()
        # Get devices current container assigned
        orig_cont = self.api.get_parent_container_for_device(device['key'])
        # Get devices current configlets
        orig_configlets = self.api.get_configlets_by_device_id(device['key'])
        # delete from inventory
        self.api.delete_device(device['systemMacAddress'])
        # sleep to allow delete to complete
        time.sleep(1)
        # verify not found in inventory
        res = self.api.get_device_by_name(device['fqdn'])
        self.assertEqual(res, {})
        # add back to inventory
        self.api.add_device_to_inventory(device['ipAddress'],
                                         orig_cont['name'],
                                         orig_cont['key'])
        # get non connected device count until it is back to equal or less
        # than the original non connected device count
        non_connect_count = self.api.get_non_connected_device_count()
        for _ in range(3):
            if non_connect_count <= orig_non_connect_count:
                break
            time.sleep(1)
            non_connect_count = self.api.get_non_connected_device_count()
        results = self.api.save_inventory()
        # Save Inventory is deprecated for 2018.2 and beyond
        if self.clnt.apiversion == 'v1':
            self.assertEqual(results['data'], 1)
        else:
            save_msg = 'Save Inventory not implemented/necessary for' +\
                       ' CVP 2018.2 and beyond'
            self.assertEqual(results['data'], 0)
            self.assertEqual(results['message'], save_msg)
        post_save_inv = self.api.get_inventory()
        self.assertEqual(len(post_save_inv), len(full_inv))
        # verify device is found in inventory again
        re_added_dev = self.api.get_device_by_name(device['fqdn'])
        self.assertEqual(re_added_dev['systemMacAddress'],
                         device['systemMacAddress'])
        # apply original configlets back to device
        results = self.api.apply_configlets_to_device("test_api_inventory",
                                                      device, orig_configlets,
                                                      create_task=True)
        # execute returned task and wait for it to complete
        task_res = self.api.execute_task(results['data']['taskIds'][0])
        self.assertEqual(task_res, None)
        task_status = self.api.get_task_by_id(results['data']['taskIds'][0])
        while task_status['taskStatus'] != 'COMPLETED':
            task_status = self.api.get_task_by_id(
                results['data']['taskIds'][0])
            time.sleep(1)

        # delete from inventory
        # self.api.delete_device(device['systemMacAddress'])
        # verify not found in inventory
        # res = self.api.get_device_by_name(device['fqdn'])
        # self.assertEqual(res, {})
        # dut = self.duts[0]
        # self.api.retry_add_to_inventory(device['ipAddress'],
        #                                device['systemMacAddress'],
        #                                dut['username'], dut['password'])

    def test_api_change_control(self):
        ''' Verify get_change_control_info and execute_change_control.
        '''
        # Set client apiversion if it is not already set
        if self.clnt.apiversion is None:
            self.api.get_cvp_info()
        chg_ctrl_name = 'test_api_%d' % time.time()
        (task_id, _) = self._create_task()
        chg_ctrl_tasks = [{
            'taskId': task_id,
            'taskOrder': 1
        }]
        chg_ctrl = self.api.create_change_control(chg_ctrl_name,
                                                  chg_ctrl_tasks,
                                                  '', '', '')
        cc_id = chg_ctrl['ccId']

        # Verify the pending change control information
        chg_ctrl_pending = self.api.get_change_control_info(cc_id)
        self.assertEqual(chg_ctrl_pending['status'], 'Pending')

        # Execute the change control
        self.api.execute_change_controls([cc_id])

        # Verify the in progress/completed change control information
        chg_ctrl_executed = self.api.get_change_control_info(cc_id)
        self.assertIn(chg_ctrl_executed['status'], ('Inprogress', 'Completed'))
        # Wait until change control is completed before continuing
        # to next test
        for _ in range(3):
            chg_ctrl_executed = self.api.get_change_control_info(cc_id)
            if chg_ctrl_executed['status'] == 'Completed':
                break
            else:
                time.sleep(1)
        # For 2018.2 give a few extra seconds for device status to get
        # back in compliance.
        if self.clnt.apiversion == 'v2':
            time.sleep(5)

    def test_api_filter_topology(self):
        ''' Verify filter_topology.
        '''
        # Set client apiversion if it is not already set
        if self.clnt.apiversion is None:
            self.api.get_cvp_info()
        # Verify the test container topology returns the test device info
        topology = self.api.filter_topology(node_id=self.container['key'])

        # Verify the test device is present in the returned data
        exp_device_key = self.device['key']
        topo_devices = [x['key'] for
                        x in topology['topology']['childNetElementList']]
        self.assertIn(exp_device_key, topo_devices)

        # Verify the test device data is consistent
        topo_dev_data = [x for x in topology['topology']['childNetElementList']
                         if x['key'] == exp_device_key][0]
        # The tempAction field can be either None or [] when empty,
        # so skip this in the comparison.
        topo_dev_data.pop('tempAction', None)
        known_dev_data = dict(self.device)
        known_dev_data.pop('tempAction', None)
        # The device containerName field appears to be null for filter
        # topology calls where the nodeID is a container ID.
        # Skip this in comparison
        topo_dev_data.pop('containerName', None)
        known_dev_data.pop('containerName', None)

        # Test expected parameter keys are in return data.
        # Test values for parameters with consistent return values
        # Ignore comparing values for keys with
        # known different return value formats
        diff_val_form_keys = ['dcaKey', 'modelName', 'isDANZEnabled',
                              'deviceInfo', 'ztpMode', 'isMLAGEnabled']
        for key in topo_dev_data:
            self.assertIn(key, known_dev_data)
            if self.clnt.apiversion == 'v1' or key not in diff_val_form_keys:
                self.assertEqual(topo_dev_data[key], known_dev_data[key])
Ejemplo n.º 19
0
from cvprac.cvp_client import CvpClient
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

clnt = CvpClient()
clnt.connect(nodes=['cvp1'], username="******",password="******")

ts = "2021-11-19T15:04:05.0Z" # rfc3339 time
uri = "/api/v3/services/compliancecheck.Compliance/GetConfig"

# Fetch the inventory
inventory = clnt.api.get_inventory()

# Iterate through all devices and get the running-config at the specified time for each device
for device in inventory:
    sn = device['serialNumber']
    data = {"request":{
        "device_id": sn,
        "timestamp": ts,
        "type":"RUNNING_CONFIG"
        }
    }
    try:
        resultRunningConfig = clnt.post(uri, data=data)[0]['config']
        with open(device['hostname']+'.cfg','w') as f:
            f.write(resultRunningConfig)
    except Exception as e:
        print("Not able to get configuration for device {} - exception {}".format(device['fqdn'], e))
Ejemplo n.º 20
0
mode = args.mode  # create or destroy
cvaas_node = args.server  # ex  "www.cv-staging.corp.arista.io"
cvaas_service_token = args.token  # Service Token created in CVaaS
device_name = args.device_name  # Device name as found in CVaaS
configlet_file = args.config_file

configlet_string = ''
with open(configlet_file, 'r') as f:
    configlet_string = f.read()

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# cvprac api reference
# https://github.com/aristanetworks/cvprac/blob/develop/cvprac/cvp_api.py

client = CvpClient()

client.connect(nodes=[cvaas_node],
               username='',
               password='',
               is_cvaas=True,
               cvaas_token=cvaas_service_token)

configlet_name = device_name + '_aws_tgw_connect'
device_info = client.api.get_device_by_name(device_name)

if mode == 'create':
    # create configlet
    client.api.add_configlet(configlet_name, configlet_string)
    # get configlet info by name
    configlet_info = client.api.get_configlet_by_name(configlet_name)
Ejemplo n.º 21
0
def connect_cvp():
    urllib3.disable_warnings()
    client = CvpClient()
    client.connect([config_dict()['server']], config_dict()['username'], config_dict()['password'])
    return client
Ejemplo n.º 22
0
import time
import os

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
ssl._create_default_https_context = ssl._create_unverified_context

parser = argparse.ArgumentParser()
parser.add_argument('--username', required=True)
parser.add_argument('--cvpip', required=True)

args = parser.parse_args()
switchuser = args.username
cvpip = args.cvpip
switchpass = getpass()

clnt = CvpClient()
clnt.connect([cvpip], switchuser, switchpass)
clntapi = CvpApi(clnt)

inventory = clntapi.get_inventory()
d1 = time.strftime("%Y_%m_%d_%H_%M_%S", time.gmtime())
os.mkdir(d1)

for device in inventory:
    hostname = device["hostname"]
    print(hostname)
    device_mac = device["systemMacAddress"]
    runningConfig = clntapi.get_device_configuration(device_mac)

    filename = hostname + "_show_run_" + d1 + ".txt"
    with open(d1 + "/" + filename, 'w') as f:
#
# Example script to generate the TerminAttr token via REST API from CVaaS and CV on-prem
# and save them to a file

from cvprac.cvp_client import CvpClient
from pprint import pprint as pp
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

# Reading the service account token from a file
with open("cvaas.tok") as f:
    token = f.read().strip('\n')

clnt = CvpClient()
clnt.connect(nodes=['www.arista.io'],
             username='',
             password='',
             is_cvaas=True,
             api_token=token)

terminattr_token = clnt.api.create_enroll_token('720h')
with open('cv-onboarding-token', 'w') as f:
    f.write(terminattr_token[0]['enrollmentToken']['token'])

primary = CvpClient()
primary.connect(nodes=['cvp1'], username='******', password='******')

terminattr_token = primary.api.create_enroll_token('720h')
Ejemplo n.º 24
0
except:
    topology = 'none'

# Temp path for where repo will be cloned to (include trailing /)
gitTempPath = '/tmp/atd/'

# Relative path within the repo to the configlet directory
configletPath = 'topologies/' + topology + '/configlets/'
ignoreConfiglets = ['readme.md']
# cvpNodes can be a single item or a list of the cluster
cvpNodes = ['192.168.0.5']
cvpUsername = '******'
cvpPassword = '******'

# Initialize the client
clnt = CvpClient()

# Attempt to connect to CVP, if it's not available wait 60 seconds
attempts = 0
while 1:
    try:
        clnt.connect(cvpNodes, cvpUsername, cvpPassword)
        if clnt.api.get_cvp_info()['version']:
            break
    except:
        attempts += 1
        print "Cannot connect to CVP waiting 1 minute attempt", attempts
        time.sleep(60)


# Function to sync configlet to CVP
Ejemplo n.º 25
0
def main():
    parser = argparse.ArgumentParser(description="Auto Provision CVP Nodes with Ansible")
    parser.add_argument("--config", action="store", help="config file location",
                                          default="config.yml")
    options = parser.parse_args()

    try:
        with open(options.config) as f:
            config = yaml.safe_load(f)
    except IOError:
        logging.info('Config file %s not found' % options.config)
        exit()

    clnt = CvpClient()
    try:
        clnt.connect(config['cvp_host'], config['cvp_user'], config['cvp_pw'])
    except KeyError:
        logging.info("CVP Credentials not found in config file")
        exit()    
                   
    # determine if there is any nodes in the ansible container
    try:
       target = config['target_container']
       prov_cont = config['provisioned_container']
    except KeyError:
       logging.info("Not container info found in config file")
       exit()
     
    try:
        verbosity = config['verbosity']
    except KeyError:
        verbosity = 'v';
    try:
        ansible_path = config['ansible_path']
    except:
        ansible_path = '/usr/bin/ansible-playbook'
                     
    devices = clnt.api.get_devices_in_container(target)
     
    for to_provision in devices:
        # move the container
        task = move_to_container(clnt, to_provision, prov_cont) 
        #cancel the task so we don't lose configs
        clnt.api.cancel_task(task['data']['taskIds'][0])
 
        # create dynamic host file
        with open('cvp_provision', 'w+') as f:
            f.write('%s  ansible_host=%s' % (to_provision['fqdn'], to_provision['ipAddress']))
                     
        logging.info("Starting to configure %s" % to_provision['fqdn'])
                     
        try:
            logging.info("Staring to configure %s via Ansible" % to_provision['fqdn'])
            output = subprocess.check_output([ansible_path, '-i', 'cvp_provision' 
                                              '-%s' % verbosity, config['playbook']])
            logging.info(output)
            logging.info("Ansible completed configuration")
                     
        except subprocess.CalledProcessError as e:
            logging.info("Ansible provision failed for host %s due to %s" % (to_provision['fqdn'], str(e)))
            # Ansible errored out so move device back
            task = move_to_container(clnt, to_provision, target) 
            #cancel the task so we don't lose configs
            clnt.api.cancel_task(task['data']['taskIds'][0])
            continue
Ejemplo n.º 26
0
 def test_clnt_init(self):
     ''' Verify CvpClient init
     '''
     clnt = CvpClient()
     self.assertIsNotNone(clnt)
     self.assertEqual(clnt.log.getEffectiveLevel(), logging.INFO)
Ejemplo n.º 27
0
    "0011": "Unauthorized User",
    "0012": "Config, Image, Extension and Device time are out of sync",
    "0013": "Config, Image and Device time are out of sync",
    "0014": "Config, Extensions and Device time are out of sync",
    "0015": "Image, Extensions and Device time are out of sync",
    "0016": "Config and Device time are out of sync",
    "0017": "Image and Device time are out of sync",
    "0018": "Extensions and Device time are out of sync",
    "0019": "Device time is out of sync"
}

# Create connection to CloudVision using Service account token
with open("token.tok") as f:
    token = f.read().strip('\n')

clnt = CvpClient()
clnt.connect(nodes=['cvp1'], username='', password='', api_token=token)


def check_devices_under_container(client, container):
    ''' container is the container ID '''

    nodeId = container['key']
    nodeName = container['name']
    api = '/ztp/getAllNetElementList.do?'
    queryParams = "nodeId={}&queryParam=&nodeName={}&startIndex=0&endIndex=0&contextQueryParam=&ignoreAdd=false&useCache=true".format(
        nodeId, nodeName)
    return client.get(api + queryParams)


container = clnt.api.get_container_by_name('TP_LEAFS')
Ejemplo n.º 28
0
def main():
    parser = argparse.ArgumentParser(description="Auto Deploy CVP Nodes")
    parser.add_argument("--config", action="store", help="config file location",
                                          default="config.yml")
    parser.add_argument("--info", action="store",
                        help="switch information yaml file",
                        default="basic-switch-info.yml")
    parser.add_argument("--lldp", action="store",
                        help="switch lldp yaml file",
                        default="basic-lldp-info.yml")
    parser.add_argument("--monitor", action="store_true",
                        help="make sure all tasks complete succesfully")
    

    options = parser.parse_args()
    info_nodes = []

    try:
        with open(options.config) as f:
            config = yaml.safe_load(f)
    except IOError:
        print 'Config file %s not found' % options.config
        exit(-1)
    try:
        with open(options.info) as i:
            fyi = yaml.safe_load(i)
    except IOError:
        print 'Info file %s not found' % options.info
        exit(-1)
    try:
        with open(options.lldp) as ld:
            neighbor_file = yaml.safe_load(ld)
    except IOError:
        print 'LLDP file %s not found' % options.lldp
        exit(-1)



    for info in fyi:
        for key, value in info.iteritems():
            if 'spine' in key.lower():
                node_type = 'SPINE'
            elif 'leaf' in key.lower():
                node_type = 'LEAF'
            try:
                info_nodes.append(Node(ip=value['mgmt-ip'], 
                                       sn=value['sn'],
                                       mac_addr=value['mac'],
                                       hostname=value['hostname'],
                                       node_type=node_type))
            except KeyError:
                print "%s did not have a required attribute (ip, sn, mac, or hostname)" % info


    clnt = CvpClient()
    clnt.connect(config['cvp_host'], config['cvp_user'], 
                 config['cvp_pw'], protocol='https')
    #get the devices in the undefined container
    devices = clnt.api.get_devices_in_container('Undefined') 
    no_matches = []
    nodes_with_tasks = []

    if devices is None:
        print 'No devices in undefined container.  Exiting'
        exit()
    else:
        node = None
        for node in devices:
            # try match a node in the undefinied container to informatin
            # in the info yaml file
            to_proceed = True
            match = find_node_match(node, info_nodes)  
            if match is not None:
                #have the netElement need to make the ma1 configlet
                sn = node['systemMacAddress']
                configlet = make_configlet(match, config)
                name = match.hostname + '-MA1-CONFIG'
                try:
                    configlet_key = clnt.api.add_configlet(name, configlet)
                except CvpApiError as e:
                    if 'Data already exists' in str(e):
                        #remove existing configlet and recreate
                        remove_old_configlet(name, clnt)
                        try:
                            configlet_key = clnt.api.add_configlet(name, configlet)
                        except CvpApiError as e:
                            # if this fails again tell user to check task list:
                            print 'unable to add configlet: %s' % str(e)
                            exit(-1)

                #add ma1 configlet to device
                configlet_to_add = {'name':name, 'key':configlet_key}
                tasks_to_monitor = []
                task = None
                print 'Attempting to deploy device %s' % node['systemMacAddress']
                # only send image if there is one in the config file
                try:
                    image = config['image']
                except KeyError:
                    image = None
                try:
                    # in this task it will move the node to the container 
                    # that matches the node_type 
                    task = clnt.api.deploy_device(node, match.node_type, 
                                              [configlet_to_add], image)   
                    print 'Deploy Device task created'
                    print 'Attempting to execute task'
                    clnt.api.execute_task(task['data']['taskIds'][0])
                    print 'Task executed...'
                    nodes_with_tasks.append(match)
                    tasks_to_monitor.append(task['data']['taskIds'][0])
                   
                except CvpApiError as e:
                    print "unable to deploy: %s due to %s" % (node['systemMacAddress'], str(e))
            else:
                print "no match found for %s" % node['systemMacAddress']
                no_matches.append(node)

        if options.monitor:
            wait_for_tasks(tasks_to_monitor, clnt)
            for sw in nodes_with_tasks:
                sw_lldp_info = (item for item in neighbor_file if item.keys()[0] == sw.hostname).next()
                host = sw_lldp_info.keys()[0]
                eapi_node = pyeapi.client.connect(host=host,
                                                  username=config['cvp_user'],
                                                  password=config['cvp_pw'],
                                                  return_node=True)
                cabling = validate_lldp(eapi_node, sw_lldp_info[host])
                if cabling['success']:
                    print 'LLDP Verified for  %s' % host
                else:
                    print 'LLDP error: %s for %s' % (cabling['msg'], host)
#!/usr/bin/env python
'''
This program uses cvprac, the CloudVision Portal API to first get a template-ID
for snapshot template: SnapshotOfConfig1 and container-ID for container: mlane1,
then POST a request for CVP to capture snapshot configs for every switch in the
cotainer.
'''
from cvprac.cvp_client import CvpClient  # Import CvpClient class module
clnt = CvpClient()  # create clnt object from CvpClient class
clnt.connect(['192.168.1.143'], 'cvpadmin', 'cvpadmin1')  # Connect to CVP

#  Next get Container information for mlane1
result = clnt.get(
    '/inventory/add/searchContainers.do?queryparam=mlane1&startIndex=0&endIndex=0'
)
# And, extract the container key or container-ID.
contnr = result['data'][0]['key']

# Get information for snapshot template: SnapshotOfConfig1
result2 = clnt.get(
    '/snapshot/getSnapshotTemplates.do?startIndex=0&endIndex=0&queryparam=SnapshotOfConfig1'
)
# And, extract it's key or template-ID
snapTemplt = result2['data'][0]['key']

# Build a dictionary which includes: "templateid" and "containerid"
parms2 = {"templateId": snapTemplt, "containerId": contnr}

# Execute a POST to the Container Snapshot module and pass the parameter dictionary: parms2
snapResult = clnt.post('/snapshot/captureContainerLevelSnapshot.do', parms2)
Ejemplo n.º 30
0
class Cvp():
    def __init__(self):

        self.cvprac = None
        self.containerTree = {}
        self.CvpApiError = None
        self.devices = {}
        self.host_to_device = {}
        self.containers = {}
        self.configlets = {}
        
        try:
            from cvprac.cvp_client import CvpClient
            from cvprac.cvp_client_errors import CvpClientError
            from cvprac.cvp_client_errors import CvpApiError
            self.CvpClientError = CvpClientError
            self.CvpApiError = CvpApiError
            self.cvprac = CvpClient()
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # to supress the warnings for https
            self.cvprac.connect([searchConfig('cvp_server')], searchConfig('cvp_user'), searchConfig('cvp_pass'))
            LOGGER.log("Successfully authenticated to CVP")
        except (ImportError, self.CvpClientError) as e:
            LOGGER.log("Unable to Init CVP; forcing debug mode")
            LOGGER.log("ERROR: {0}".format(e))
            global DEBUG
            DEBUG = True
            
        
    def populate(self):
        
        try:
            LOGGER.log("-loading containers; please wait...")
            self.containers = {item['name'].lower():item for item in self.cvprac.api.get_containers()['data']}
            LOGGER.log("-loading configlets; please wait...")
            self.configlets = {item['name'].lower():item for item in self.cvprac.api.get_configlets()['data']}
            
            for name, cont in self.containers.items():
                self.containerTree[name] = [_name for _name, _cont in self.containers.items() if _cont['parentName'] == cont['name']]
                
            
            LOGGER.log("-loading devices; please wait...")
            for device in self.cvprac.api.get_inventory():
                sn = device['serialNumber'].lower()
                host = device['hostname'].lower()
                LOGGER.log("-loading {0} configlets; please wait...".format(host))
                configlets = self.cvprac.api.get_configlets_by_device_id(device['systemMacAddress'])
                device['configlets'] = {item['name'].lower():item for item in configlets}
                
                self.devices[sn] = device
                self.host_to_device[host] = self.devices[sn]
            
        except:
            LOGGER.log("Unable to connect to CVP Server")
            sys.exit(0)
    
    def getBySerial(self, sn):
        return self.devices.get(sn.lower(), None)
    
    def getByHostname(self, hostname):
        return self.host_to_device.get(hostname.lower(), None)
    
    def getContainerByName(self, name):
        return self.containers.get(name.lower(), None)
    
    def getContainerDevices(self, containerName, follow = False):
        containerName = containerName.lower()
        tree = [containerName] + self.containerTree[containerName] if follow else [containerName]
        return [device for device in self.devices.values() if device['containerName'].lower() in tree]
    
    def fetchDevices(self, search, follow_child_containers = False):
        search = search if type(search) == list else [search]
        devices = []
        for _search in search:
            
            try:
                device = CVP.getBySerial(_search) or CVP.getByHostname(_search)
                if device:
                    devices.append((device,))
                    continue
                else:
                    devices.append(CVP.getContainerDevices(_search, follow_child_containers))
            except KeyError as e:
                LOGGER.log("Could not find {0}".format(_search))
        return list(chain.from_iterable(devices))
    
    def createConfiglet(self, configlet_name, configlet_content):
        # Configlet doesn't exist let's create one
        LOGGER.log("--creating configlet {0}; please wait...".format(configlet_name))
        self.cvprac.api.add_configlet(configlet_name, configlet_content)
        return self.cvprac.api.get_configlet_by_name(configlet_name)
                
        
    def updateConfiglet(self, configlet, new_configlet_content):
        # Configlet does exist, let's update the content only if not the same (avoid empty task)
        configlet_name = configlet['name']
        LOGGER.log("--found configlet {0}".format(configlet_name))
        if configlet['config'] != new_configlet_content:
            LOGGER.log("---updating configlet {0}; please wait...".format(configlet_name))
            self.cvprac.api.update_configlet(new_configlet_content, configlet['key'], configlet_name)
        return self.cvprac.api.get_configlet_by_name(configlet_name)
                
    def deployDevice(self, device, container, configlets_to_deploy):
        try:
            ids = self.cvprac.api.deploy_device(device.cvp, container, configlets_to_deploy)
        except self.CvpApiError as e:
            LOGGER.log("---deploying device {0}: failed, could not get task id from CVP".format(device.hostname))
        else:
            ids = ','.join(map(str, ids['data']['taskIds']))
            LOGGER.log("---deploying device {0}: {1} to {2} container".format(device.hostname, device.mgmt_ip, device.container))
            LOGGER.log("---CREATED TASKS {0}".format(ids))
            
    def applyConfiglets(self, to, configlets):
        app_name = "CVP Configlet Builder"
        to = to if type(to) == list else [to]
        configlets = configlets if type(configlets) == list else [configlets]
        toContainer = None
        toDevice = None
        
        #dest is a container, sn. or hostname string
        for dest in to:
            
            toContainer = self.getContainerByName(dest)
            if toContainer:
                LOGGER.log("---applying configlets to {0}; please wait...".format(toContainer.name))
                _result = self.cvprac.api.apply_configlets_to_container(app_name, toContainer, configlets)
                dest = toContainer
            else:
                #apply to device
                toDevice = getBySerial(dest) or getByHostname(dest)
                dest = toDevice.hostname
                LOGGER.log("---applying configlets to {0}; please wait...".format(dest))
                _result = self.cvprac.api.apply_configlets_to_device(app_name, toDevice.cvp, configlets) if toDevice else None
            
            if not (toDevice or toContainer):
                errorOn = [_conf['name'] for _conf in configlets]
                LOGGER.log("---failed to push {0}; {1} not found".format(','.join(errorOn), dest))
            elif _result and _result['data']['status'] == 'success':
                
                LOGGER.log("---CREATED TASKS {0}".format(','.join(map(str, _result['data']['taskIds']))))
                
                
        return None    
from openpyxl.styles import Font
from openpyxl.styles.borders import Border, Side
import time
import datetime
import getpass

print "\nEnter CVP login details:-\n"

CVP_HOST = raw_input("CVP IP:")
CVP_USER = raw_input("Username:"******"Password: ")

ssl._create_default_https_context = ssl._create_unverified_context
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

client = CvpClient()
client.connect([CVP_HOST], CVP_USER, CVP_PW, protocol='https')

# Create a workbook and add a worksheet.
wb = Workbook()
sheet = wb.create_sheet(title='CVP_Inventory_Sheet', index=0)
ws = wb.active

# Data can be assigned directly to cells
ws['A1'] = 'Switch Hostname'
ws['B1'] = 'Switch MGMT IP'
ws['C1'] = 'EOS_Version'
ws['D1'] = 'Model'
ws['E1'] = 'Serial_Number'
ws['F1'] = 'MAC_Address'
Ejemplo n.º 32
0
class TestClient(unittest.TestCase):
    """ Unit test cases for CvpClient
    """

    # pylint: disable=protected-access
    # pylint: disable=invalid-name

    def setUp(self):
        """ Setup for CvpClient unittests
        """
        self.clnt = CvpClient()
        nodes = ['1.1.1.1']
        self.clnt.nodes = nodes
        self.clnt.node_cnt = len(nodes)
        self.clnt.node_pool = cycle(nodes)

    def test_create_session_default_https(self):
        """ Test connection to CVP nodes will default to https.
        """
        url = 'https://1.1.1.1:443/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.return_value = None
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)

    def test_create_session_https_port(self):
        """ Test https session with user provided port.
        """
        self.clnt.port = 7777
        url = 'https://1.1.1.1:7777/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.return_value = None
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)

    def test_create_session_http_fallback(self):
        """ Test a failed https connection will attempt to fallback to http.
        """
        self.clnt.port = None
        url = 'http://1.1.1.1:80/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.side_effect = [
            'Failed to connect via https', None
        ]
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)
        self.assertEqual(self.clnt.error_msg, '\n')

    def test_create_session_http_fallback_port(self):
        """ Test http fallback will use a user provided port number.
        """
        self.clnt.port = 8888
        url = 'http://1.1.1.1:8888/web'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.side_effect = [
            'Failed to connect via https', None
        ]
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)
        self.assertEqual(self.clnt.error_msg, '\n')

    def test_create_session_no_http_fallback_with_cert(self):
        """ If user passes a certificate to CvpClient it will only attempt to
            use https and not fall back to http.
        """
        self.clnt.port = None
        self.clnt.cert = 'cert'
        url = 'https://1.1.1.1:443/web'
        error = '\n1.1.1.1: Failed to connect via https\n'
        self.clnt._reset_session = Mock()
        self.clnt._reset_session.return_value = 'Failed to connect via https'
        self.clnt._create_session(all_nodes=True)
        self.assertEqual(self.clnt.url_prefix, url)
        self.assertEqual(self.clnt.error_msg, error)

    def test_make_request_good(self):
        """ Test request does not raise exception and returns json.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        request_return_value = Mock()
        self.clnt.session.get.return_value = request_return_value
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        request_return_value.json.assert_called_once_with()
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_timeout(self):
        """ Test request timeout exception raised if hit on multiple nodes.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.side_effect = ReadTimeout('Timeout')
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 3
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 3
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(ReadTimeout):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_http_error(self):
        """ Test request http exception raised if hit on multiple nodes.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.side_effect = HTTPError('HTTPError')
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(HTTPError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_no_session_error(self):
        """ Test request exception raised if hit on multiple nodes and
            _create_session fails to reset clnt.session.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.side_effect = HTTPError('HTTPError')
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 0.01
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock(return_value='Good')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(HTTPError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_response_error(self):
        """ Test request exception raised from CVP response data.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.return_value = Mock()
        self.clnt._create_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock()
        self.clnt._is_good_response.side_effect = CvpApiError('CvpApiError')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(CvpApiError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_response_error_unauthorized(self):
        """ Test request exception raised if CVP responds unauthorized user.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.return_value = Mock()
        self.clnt._create_session = Mock()
        self.clnt._reset_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock()
        self.clnt._is_good_response.side_effect = CvpApiError(
            msg='Unauthorized User')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(CvpApiError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')

    def test_make_request_response_error_logout(self):
        """ Test request exception raised if CVP logout error hit.
        """
        self.clnt.session = Mock()
        self.clnt.session.return_value = True
        self.clnt.session.get.return_value = Mock()
        self.clnt._create_session = Mock()
        self.clnt._reset_session = Mock()
        self.clnt.NUM_RETRY_REQUESTS = 2
        self.clnt.connect_timeout = 2
        self.clnt.node_cnt = 2
        self.clnt.url_prefix = 'https://1.1.1.1:7777/web'
        self.clnt._is_good_response = Mock()
        self.clnt._is_good_response.side_effect = CvpSessionLogOutError('bad')
        self.assertIsNone(self.clnt.last_used_node)
        with self.assertRaises(CvpSessionLogOutError):
            self.clnt._make_request('GET', 'url', 2, {'data': 'data'})
        self.assertEqual(self.clnt.last_used_node, '1.1.1.1')
Ejemplo n.º 33
0
    """
    Use Arista provided script from https://github.com/arista-netdevops-community/eos-scripts
    TODO Migrate to CVP API when it supports it
    """
    rc = os.system("python eos_download.py --api %s --ver %s" %
                   (apikey, targetversion))
    assert (rc == 0)
    assert (os.path.isfile(targetimage))
    return True


def precheck():
    pass


clnt = CvpClient()
clnt.connect([os.environ['CVP_HOST']], 'cvpadmin', os.environ['CVP_PASS'])
latestbundle = clnt.api.get_image_bundle_by_name('EOS-latest')

# we extract the images in there and upgrade the EOS one
EOS = list(
    filter(lambda x: x['imageFileName'].startswith('EOS'),
           latestbundle['images']))[0]
notEOS = list(
    filter(lambda x: not x['imageFileName'].startswith('EOS'),
           latestbundle['images']))

print("currentlatest: ", EOS['name'])
targetRelease = findTargetVersion(EOS['name'], extractReleases())

if not targetRelease:
Ejemplo n.º 34
0
 def test_clnt_init_syslog(self):
     ''' Verify CvpClient init with syslog argument
     '''
     clnt = CvpClient(syslog=True)
     self.assertIsNotNone(clnt)
  _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
# Legacy Python that doesn't verify HTTPS certificates by default
  pass
else:
# Handle target environment that doesn't support HTTPS verification
  ssl._create_default_https_context = _create_unverified_https_context

ssl._create_default_https_context = ssl._create_unverified_context
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

cvp_username = CVPGlobalVariables.getValue(GlobalVariableNames.CVP_USERNAME)
cvp_password = CVPGlobalVariables.getValue(GlobalVariableNames.CVP_PASSWORD)

clnt = CvpClient()
clnt.connect(['localhost'], cvp_username, cvp_password)
configlet_name = "cvp_1_site_users_pwd_config"

output = clnt.api.get_configlet_by_name(name = configlet_name)
config = output["config"]
key = output["key"]

new_config = ""

for line in config.splitlines():
  if "secret" in line or "enable" in line:
    words = line.split()
    for x in range(len(words)):
      if words[x] == "secret" and words[x+1] != "sha512":
        words[x+1] = "sha512 " + crypt.crypt(words[x+1], "$6$saltsalt$")
Ejemplo n.º 36
0
from pprint import pprint
from cvprac.cvp_client import CvpClient
from cvprac.cvp_api import CvpApi
import urllib3

import time
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning
                         )  # This will disable invalid cert warnings

client = CvpClient()

client.connect(['cvp.lab.local'], 'jpatterson', 'P3pp3r101!')

cvp = CvpApi(client)
# test = cvp.get_cvp_info()
# print test
#
# gettask = cvp.get_tasks()
# pprint(gettask)
'''Get inventory of CVP, then strip out FQDN of hostname and present just hostname:'''
# host_list = []
# def hostname(filter=''):
#     inventory = cvp.get_inventory(query=filter)
#     full_fqdn = 'lab.local'
#     for value in inventory:
#         if full_fqdn in value['fqdn']:
#             fqdn_strip = value['fqdn'][0:-10]
#             host_list.append(fqdn_strip)
#     return host_list
#
# hostname()
Ejemplo n.º 37
0
from cvprac.cvp_client import CvpClient
from pprint import pprint
import json
import sys
from jinja2 import Environment, FileSystemLoader
import itertools

robotlist = []
countlist = []

client = CvpClient()
client.connect(['10.20.30.142'],'daniel', 'daniel123')
inventory = client.api.get_inventory()

def initcvpyaml():
  sys.stdout = open('cvp.yaml', 'w')
  print '---'
  print 'TRANSPORT: https'
  print 'PORT: 443'
  print 'USERNAME: daniel'
  print 'PASSWORD: daniel123'
  print '   '
  print 'RUNFORMAT: suite'
  print '   ' 
  print 'PROD_TAGS:'
  print '  - ignoretags'
  print '   '
  print 'testfiles:'
  print '  - network_validation'
  print '   ' 
  print 'nodes:'