예제 #1
0
def connect_to_cvp(parameters, log_level='WARNING'):
    """Create a CVP connection.

    parameters option should at least contain following elements:
        - username
        - password
        - cvp (server IP or DNS hostname)

    Parameters
    ----------
    parameters : dict
        Object with all information to create connection
    log_level : str
        Log level to use for CvpClient logger. Default is WARNING.

    Returns
    -------
    cvprac.CvpClient()
        cvp client object

    """
    client = CvpClient(log_level=log_level)
    try:
        client.connect(nodes=[parameters.cvp], username=parameters.username,
                       password=parameters.password, connect_timeout=10, protocol=CVP['PROTO'], port=CVP['PORT'])
        logging.info('* connected to %s', CVP['HOST'])
    except CvpLoginError, e:
        # If error, then, printout message and quit program
        # If server cannot be reached, then no need to go further
        logging.error('! can\'t connect to %s', parameters.cvp)
        logging.error('! error message is: %s', str(e).replace('\n', ' '))
        quit()
예제 #2
0
def main():
    parser = argparse.ArgumentParser(description="Auto Deploy CVP Nodes")
    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:
        print 'Config file %s not found' % options.config
        exit()

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

    if devices is None:
        print 'No devices in undefined container.  Exiting'
        exit()
    else:
        node = None
        for node in devices:
            print node
            #have the netElement need to make the ma1 configlet
            sn = node['systemMacAddress']
            configlet = make_configlet(node['ipAddress'], config)
            name = sn + '-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()

            #add ma1 configlet to device
            configlet_to_add = {'name': name, 'key': configlet_key}
            task = None
            print 'Attempting to deploy device %s' % node['systemMacAddress']
            try:
                task = clnt.api.deploy_device(node, config['target_container'],
                                              [configlet_to_add],
                                              config['image'])
                print 'Deploy Device task created'
                print 'Attempting to execute task'
                clnt.api.execute_task(task['data']['taskIds'][0])
                print 'Task executed...'

            except CvpApiError as e:
                print "unable to deploy: %s due to %s" % (
                    node['systemMacAddress'], str(e))
예제 #3
0
def main():
    args = parseArgs()
    username = args.user
    password = args.password
    if password is None:
        print("Please provide a password for the user {}".format(username))
        password = getpass("Password:"******",")]
    inventory_file = args.inventory
    switch_info_dict = parse_switch_info_file(inventory_file)
    cvp = CvpClient()
    cvp.connect(cvp_addresses, username, password)
    inventory = cvp.api.get_inventory()
    for switch in inventory:
        #Check to see if switch in spreadsheet and get VRF
        try:
            switch_details = switch_info_dict[switch["hostname"]]
        except KeyError:
            print("Could not find {}'s serial number in spreadsheet".format(
                switch["hostname"]))
            continue
        deploy_device_with_no_configlets(cvp,
                                         switch,
                                         switch_details["Target Container"],
                                         switch_details["Image Bundle"],
                                         include_container_configlets=True)
예제 #4
0
def connect_cvp():
    urllib3.disable_warnings()
    client = CvpClient()
    client.connect([config_dict()['server']],
                   config_dict()['username'],
                   config_dict()['password'])
    return client
예제 #5
0
def load_cvp_data():
    clnt = CvpClient()
    clnt.connect([cvp_ip], cvp_user, cvp_password)
    api = CvpApi(clnt)
    leaf_inventory = api.get_devices_in_container('LEAF')
    leaf_fqdn_list = list()
    for element in leaf_inventory:
        hostname = re.split('\.', element['fqdn'])[0]
        leaf_fqdn_list.append(hostname)
    return leaf_fqdn_list
예제 #6
0
def main():
    client = CvpClient()
    client.connect(['52.53.222.131'], 'arista', 'arista')
    inventory = client.api.get_inventory()
    all_hosts = []
    for dev in inventory:
        all_hosts.append(dev['ipAddress'])
    formatted_inventory = dict(arista=dict(hosts=all_hosts))
    output = json.dumps(formatted_inventory, indent=2)
    print output
    sys.exit(0)
예제 #7
0
def connect(module):
    client = CvpClient()
    try:
        client.connect(
            [module.params['host']],
            module.params['username'],
            module.params['password'],
            protocol=module.params['protocol'],
            port=module.params['port'],
        )
    except CvpLoginError, e:
        module.fail_json(msg=str(e))
예제 #8
0
def main():
    options = parseargs()
    # Make connection to CVP
    client = CvpClient()
    client.connect([options.cvp], options.user, options.passw)
    resp = client.api.get_cvp_info()
    if resp is None:
        print "Failed to get CVP info. Exiting"
        sys.exit(1)

    dev_info = client.api.get_device_by_name(options.device)
    if dev_info is None:
        print "Unable to find device %s. Exiting" % options.device
        sys.exit(1)
    print "FOUND DEVICE INFO"

    dev_configlets = client.api.get_configlets_by_device_id(
        dev_info["systemMacAddress"])
    if dev_configlets is None:
        print "Found no configlets for device %s. Exiting" % options.device
        sys.exit(1)
    print "FOUND DEVICE CONFIGLETS"
    reconcile_configlet = None
    for configlet in dev_configlets:
        if "reconciled" in configlet and configlet["reconciled"] is True:
            reconcile_configlet = configlet

    if reconcile_configlet is None:
        print "No reconcile configlet for device %s. Exiting" % options.device
        sys.exit(1)
    print "FOUND DEVICE RECONCILE CONFIGLET"
    # Call function to parse interfaces and non-interfaces from Recocile Configlet
    automation_configlet_dict, reconcile_configlet_list = parse_reconcile_config(
        reconcile_configlet["config"])
    # Call function to update automation configlets with necessary ports
    configlet_upload(client, options.device, automation_configlet_dict)
    # Update Reconcile Configlet to remove interfaces moved to automation
    print "UPDATING RECONCILE CONFIGLET TO REMOVE INTERFACES"
    reconcile_config = ""
    for line in reconcile_configlet_list:
        reconcile_config += str(line + "\n")
    data = {
        "name": reconcile_configlet["name"],
        "config": reconcile_config,
        "key": reconcile_configlet["key"],
        "reconciled": True
    }
    resp = client.post(
        "/provisioning/updateReconcileConfiglet.do?netElementId=" +
        dev_info["systemMacAddress"],
        data=data)
예제 #9
0
def add_configlet(configlet_name, configlet_string, switch_list):
    clnt = CvpClient()
    clnt.connect([cvp_ip], cvp_user, cvp_password)
    api = CvpApi(clnt)

    api.add_configlet(configlet_name, configlet_string)
    for switch_name in switch_list:
        switch_id = api.get_device_by_name(switch_name)
        configlet_id = api.get_configlet_by_name(configlet_name)
        api.apply_configlets_to_device('3rd-party',
                                       switch_id, [configlet_id],
                                       create_task=True)

    return 'Ignore'
예제 #10
0
 def _open_cvp_session(self):
     try:
         client = CvpClient()
         client.connect(
             nodes=self.cvp_hosts,
             username=self.cvp_user,
             password=self.cvp_password,
             request_timeout=300,
             connect_timeout=30
         )
         return(client)
     except CvpLoginError as e:
         print(f"Cannot connect to CVP API: {e}")
         exit()
def main():
    args = parseArgs()
    username = args.user
    password = args.password
    if password is None:
        print("Please provide a password for the user {}".format(username))
        password = getpass("Password:"******",")]

    cvp = CvpClient()
    cvp.connect(cvp_addresses, username, password)

    #Define list of switches we will consolidate configlets
    switches = []

    print("Retrieving inventory")
    #Check if target is a container
    container = None
    containers = cvp.api.get_containers()["data"]
    for c in containers:
        if c["name"] == args.target:
            container = c
            break

    #If no container is found from the target name, assume it is a device
    if container is not None:
        #Get devices in/under container
        if args.mode == "extended":
            switches = cvp.api.get_devices_under_container(args.target)
        else:
            switches = cvp.api.get_devices_in_container(args.target)

    else:
        inventory = cvp.api.get_inventory()
        for device in inventory:
            if device['hostname'] == args.target:
                switches.append(device)
                break
    print("Successfully retrieved inventory")
    if type(args.cancel) != bool and re.match(r'(?i)True', args.cancel):
        cancel_tasks = True
    else:
        cancel_tasks = False
    for switch in switches:
        #Check to see if switch in spreadsheet and get VRF
        consolidate_configlets(cvp,
                               switch,
                               include_container_configlets=True,
                               cancel_tasks=cancel_tasks)
예제 #12
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, e:
        module.fail_json(msg=str(e))
예제 #13
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
예제 #14
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'])
예제 #15
0
def getVersion(mac):
    try:
        clnt = CvpClient()
        clnt.connect(['{}'.format(host)], user, password)
        serialNumber = clnt.api.get_device_by_mac(mac)['serialNumber']
        version = clnt.get('/api/v1/rest/{}/Eos/image'.format(serialNumber))['notifications'][0]['updates']['version']['value']

    except:
        if trace:
            sys.stderr.write('cvprac api call to {} unsuccessful.\n'.format(mac))

        return None

    else:
        if trace:
            sys.stderr.write('cvprac api call to {} successful.\n'.format(mac))

        return version
예제 #16
0
def connect(hostname, username, password, port = 443):
    ''' Connects to a CVP device using user provided credentials from opts.
    '''
    socket.setdefaulttimeout(3)
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    client = CvpClient()
    try:
        client.connect([hostname],
                       username,
                       password,
                       protocol="https",
                       port=port)
    
    except CvpLoginError as error:
        timestamp = datetime.now().replace(microsecond=0)
        sys.stderr.write('{} {}ERROR{}: {}.\n'.format(timestamp, bcolors.ERROR, bcolors.NORMAL, error))
        sys.exit(1)

    return client
예제 #17
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'])
예제 #18
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()
    connection = Connection(module._socket_path)
    host = connection.get_option("host")
    port = connection.get_option("port")
    user = connection.get_option("remote_user")
    pswd = connection.get_option("password")
    try:
        client.connect([host],
                       user,
                       pswd,
                       protocol="https",
                       port=port,
                       )
    except CvpLoginError, e:
        module.fail_json(msg=str(e))
예제 #19
0
class CVP():
    def __init__(self):
        try:
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning
                                     )  # to supress the warnings for https
            self.cvprac = CvpClient()
            config = Global_Config.objects.get(name='master').params
            self.cvprac.connect(config['server'], config['user'],
                                config['password'])
        except:
            pass

    def connect(self):
        try:
            config = Global_Config.objects.get(name='master').params
            self.cvprac.connect(config['server'], config['user'],
                                config['password'])
            return True
        except Exception as e:
            print(e)
            return False

    def status(self):
        try:
            self.cvprac.api.get_cvp_info()
            return True
        except Exception as e:
            print(e)
            if self.connect():
                return True
            else:
                return False

    def call(self, endpoint):
        if self.status():
            try:
                return getattr(self.cvprac.api, endpoint)()
            except CvpClientError as e:
                return False
        else:
            return False
예제 #20
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'formList': list,
            u'main_script': dict,
        }
        # Handle unicode type for Python 2 vs Python 3
        if sys.version_info.major < 3:
            exp_data[u'name'] = (unicode, str)
        else:
            exp_data[u'name'] = str
        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,
            'total': int,
            'configletMapper': dict,
        }
        for key in exp_data:
            self.assertIn(key, result)
            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,
            'total': int,
            'configletMapper': dict,
        }
        for key in exp_data:
            self.assertIn(key, result)
            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,
            }
            for key in exp_data:
                self.assertIn(key, result)
                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,
            }
            for key in exp_data:
                self.assertIn(key, result)
                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)
        # Delete test configlet
        self.api.delete_configlet(name, key)

    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_cancel_image(self):
        ''' Verify add_image and cancel_image
        '''
        # Get number of current images
        orig_images = self.api.get_images()

        # Copy the test image file with a timestamp appended
        image_file_name = 'image-file-%s.swix' % time.time()
        image_file = 'test/fixtures/%s' % image_file_name
        shutil.copyfile('test/fixtures/image-file.swix', image_file)

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

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

        # Check return status good
        self.assertIn('result', add_response)
        self.assertEqual(add_response['result'], 'success')

        # Verify image added
        post_add_images = self.api.get_images()
        self.assertEqual(orig_images['total'] + 1, post_add_images['total'])

        # Cancel/Discard added image
        cancel_resp = self.api.cancel_image(image_file_name)
        self.assertEqual(cancel_resp['data'], 'success')

        # Verify image cancelled/discarded
        post_cancel_images = self.api.get_images()
        self.assertEqual(orig_images['total'], post_cancel_images['total'])

    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_delete_image_bundle(self):
        ''' Verify save_image_bundle and update_image_bundle
        '''
        # pylint: disable=too-many-locals
        # Get an existing bundle
        bundles = self.api.get_image_bundles()
        total = bundles['total']
        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)

        # Assert bundle added
        new_bundles = self.api.get_image_bundles()
        new_total = new_bundles['total']
        self.assertEqual(total + 1, new_total)

        # 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)
        self.assertRegexpMatches(result['data'],
                                 'Image bundle updated successfully')

        # 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)
        bundle_id = bundle['id']
        bundle_name = bundle['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)

        # Remove new bundle
        result = self.api.delete_image_bundle(bundle_id,
                                              bundle_name)
        self.assertEqual(result['data'], 'success')

        # Assert new bundle successfully removed
        new_bundles = self.api.get_image_bundles()
        new_total = new_bundles['total']
        self.assertEqual(total, new_total)

    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(2)
        # 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])
예제 #21
0
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"

try:
    clnt.api.add_user(username, password, role, status, first_name, last_name,
                      email, utype)
예제 #22
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(['cvp1'], 'username', 'password')

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

device_name = "tp-avd-leaf2"
device = clnt.api.get_device_by_name(device_name)

clnt.api.apply_image_to_device(image, device)
예제 #23
0
configletPath = ''
ignoreConfiglets = ['.git','.md']
# cvpNodes can be a single item or a list of the cluster
cvpNodes = ['54.183.233.155']
cvpUsername = '******'
cvpPassword = '******'


# Initialize the client
cvpClient = CvpClient()

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

# Function to determine if string passed is python or just text
def is_python(code):
   try:
       ast.parse(code)
   except SyntaxError:
       return False
   return True
예제 #24
0
class TestCvpClient(DutSystemTest):
    ''' Test cases for the CvpClient class.
    '''

    # pylint: disable=too-many-public-methods
    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)
        dut = self.duts[0]
        self.clnt.connect([dut['node']], dut['username'], dut['password'])
        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
        '''
        # Get the next task ID
        task_id = self._get_next_task_id()

        # Update the lldp time in the first configlet in the list.
        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
        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
        '''
        result = self.api.get_cvp_info()
        self.assertIsNotNone(result)
        self.assertIn('version', result)

    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)
        status = result['workOrderUserDefinedStatus']
        self.assertEqual(status, 'Pending')

        # Restore the configlet to what it was before the task was created.
        configlet = self.dev_configlets[0]
        self.api.update_configlet(org_config, configlet['key'],
                                  configlet['name'])

        # Test cancel_task
        self.api.cancel_task(task_id)

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

        # Check compliance
        self.test_api_check_compliance()

    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
        '''
        with self.assertRaises(CvpApiError):
            self.api.get_task_by_id('BOGUS')

    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_configlet_by_name(self):
        ''' Verify get_configlet_by_name
        '''
        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_configlet_history(self):
        ''' Verify get_configlet_history
        '''
        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_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 _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 _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_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 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_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
        result = self.api.get_task_by_id(task_id)
        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
        result = self.api.get_task_by_id(task_id)
        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_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_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_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_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_image_to_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'])

            # 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 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])
            task = self.api.get_task_by_id(taskids[0])
            self.assertIsNotNone(task)
            self.assertEqual(task['workOrderUserDefinedStatus'], 'Cancelled')

    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'])
예제 #25
0
# Define URL for local eAPI connection. Uses local loopback
local_url_string = "https://{}:{}@{}/command-api".format(
    username, password, "127.0.0.1")
local_switch_req = Server(local_url_string)

# Open syslog for log creation
syslog.openlog('PeerInterfaceEnabler', 0, syslog.LOG_LOCAL4)

# Connect to CVP for configlet push if necessary
if cvp_bool == True:
    from cvprac.cvp_client import CvpClient
    from cvprac.cvp_client_errors import CvpApiError
    try:
        cvp = CvpClient(syslog=True, filename='cvprac_log')
        cvp.connect(cvp_ip, username, password)
    except:
        syslog.syslog(
            "%%PeerInt-6-LOG: Unable to connect to CVP. Continuing script")
        pass


# Setup timeout function and signal
def handler(signum, frame):
    syslog.syslog("%%PeerInt-6-LOG: Timed out waiting for peer eAPI.")
    raise Exception("timeout")


signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
예제 #26
0
#Openfaas magic.
#I need to get the entire JSON data with the device because things may need it!  This includes also a new way to send the post request header.
#Dockerize this thing with arguments for container, IP, Username and password.

from cvprac.cvp_client import CvpClient
import json
import time
import urllib3
import requests

urllib3.disable_warnings()
client = CvpClient()
client.connect(['10.20.30.142'], 'daniel', 'daniel123')
url = 'http://10.20.30.147:31112/function/hello-python'
data_list1 = []
data_list2 = []
data_device = {}


def get_devices(data_list):
    inventory = client.api.get_devices_in_container('DC1-Leaf')
    data = json.dumps(inventory, sort_keys=True, indent=4)
    data_dict = json.loads(data)
    for devices in data_dict:
        showdevices = devices['ipAddress']
        data_list.append(showdevices)
        showhosts = devices['fqdn']
        data_list.append(showdevices)
        data_device.update({showhosts: showdevices})

예제 #27
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'])
예제 #28
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)
        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):
        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):
        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'],
                          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'])
예제 #29
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    
예제 #30
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)
예제 #31
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

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

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

tags_common = [{
    "key": "topology_hint_pod",
    "value": "tp-avd-pod1"
}, {
    "key": "topology_hint_datacenter",
    "value": "tp-avd-dc1"
}]
tags_leaf1 = [{"key": "topology_hint_rack", "value": "tp-avd-leafs1"}]
tags_leaf2 = [{"key": "topology_hint_rack", "value": "tp-avd-leafs2"}]
tags_spines = [{"key": "topology_hint_rack", "value": "tp-avd-spines"}]

# Create workspace
display_name = 'TestTagCVPRAC'
workspace_id = "TestTagCVPRAC"
clnt.api.workspace_config(workspace_id, display_name)

### Create tags
예제 #32
0
def main():

    compliance = {
        "0001": "Config is out of sync",
        "0003": "Config & image out of sync",
        "0004": "Config, Image and Device time are in sync",
        "0005": "Device is not reachable",
        "0008": "Config, Image and Extensions are out of sync",
        "0009": "Config and Extensions are out of sync",
        "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",
        "0016": "Config and Device time are out of sync"
    }
    # Create connection to CloudVision
    clnt = CvpClient()

    parser = argparse.ArgumentParser(
        description=
        'Script to recreate a task, if a previous config push was cancelled')
    parser.add_argument('-u', '--username', default='username')
    parser.add_argument('-p', '--password', default=None)
    parser.add_argument('-c', '--cvpserver', action='append')
    parser.add_argument('-f', '--filter', action='append', default=None)
    args = parser.parse_args()

    if args.password is None:
        args.password = getpass()

    for cvpserver in args.cvpserver:
        print("Connecting to %s" % cvpserver)
        try:
            clnt.connect(nodes=[cvpserver],
                         username=args.username,
                         password=args.password)
        except Exception as e:
            print("Unable to connect to CVP: %s" % str(e))

        # Get the current CVP version
        cvp_release = clnt.api.get_cvp_info()['version']
        if parse_version(cvp_release) < parse_version('2020.3.0'):
            # For older CVP, we manually trigger a compliance check
            try:
                clnt.api.check_compliance('root', 'container')
            except:
                # Bad practice, but the check compliance applied to a container can't actually work
                # since the complianceIndication  key doesn't exist on the container level
                pass
        else:
            # with continuous compliance checks, triggering the check is no longer required
            pass

        device_filters = []
        if args.filter is not None:
            for entry in args.filter:
                device_filters.extend(entry.split(','))

        # Get inventory
        print("Collecting inventory...")
        devices = clnt.api.get_inventory()
        print("%d devices in inventory" % len(devices))

        for switch in devices:
            if (switch['status'] == 'Registered'
                    and switch['parentContainerId'] != 'undefined_container'):

                if len(device_filters) > 0:
                    # iterate over device filters, and update task for
                    # any devices not in compliance

                    for filter_term in device_filters:
                        print("Checking device: %s" % switch['hostname'])
                        if filter_term in switch['hostname']:
                            # generate configlet list
                            cl = clnt.api.get_configlets_by_device_id(
                                switch['systemMacAddress'])
                            # generate a task if config is out of sync
                            if switch['complianceCode'] in compliance.keys():
                                print(
                                    clnt.api.apply_configlets_to_device(
                                        "", switch, cl))
                            else:
                                print("%s is compliant, nothing to do" %
                                      switch['hostname'])
                        else:
                            print("Skipping %s due to filter" %
                                  switch['hostname'])
                else:
                    print("Checking device: %s" % switch['hostname'])
                    cl = clnt.api.get_configlets_by_device_id(
                        switch['systemMacAddress'])
                    # generate a task if config is out of sync
                    if switch['complianceCode'] in compliance.keys():
                        print(
                            clnt.api.apply_configlets_to_device(
                                "", switch, cl))

            else:
                print("Skipping %s, device is unregistered for provisioning" %
                      switch['hostname'])

    return 0
예제 #33
0
# Use of this source code is governed by the Apache License 2.0
# that can be found in the COPYING file.
#
# Get list of configlets in parallel

from cvprac.cvp_client import CvpClient
import ssl
from concurrent.futures import ThreadPoolExecutor
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="******")

import time
from functools import wraps


def get_list_of_configlets(configlets):
    """
    Create a thread pool and download specified urls
    """

    futures_list = []
    results = []

    with ThreadPoolExecutor(max_workers=40) as executor:
        for configlet in configlets:
예제 #34
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:'