Esempio n. 1
0
    def run(self):
        """
        Method run instructs Cisco DNAC to execute the command set stored in
        the CommandRunner object.  It does not wait for the task to
        complete on Cisco DNA Center.  It does, however, create a new Task
        object, saves it in the __task attribute, checks the task, and
        then returns the task's status.  See the task.py module for
        valid task states.  When using this function, the programmer
        must handle task monitoring.

        Parameters:
            none

        Return Values:
            str: The current state of the command's progress.

        Usage:
            d = Dnac()
            cmd = CommandRunner(d, 'aName')
            cmdState = cmd.run()
        """
        url = self.dnac.url + self.resource
        results, status = self.crud.post(url,
                                         headers=self.dnac.hdrs,
                                         body=self.__cmds,
                                         verify=self.verify,
                                         timeout=self.timeout)
        if status != ACCEPTED:
            raise DnacApiError(MODULE, 'run', REQUEST_NOT_ACCEPTED, url,
                               ACCEPTED, status, ERROR_MSGS[status],
                               str(results))
        task_id = results['response']['taskId']
        self.__task = Task(self.dnac, task_id)
        return self.__task.check_task()
Esempio n. 2
0
    def commit_template(self, comments='', timeout=5):
        """
        The commit_template updates the parent template to its next version.  Once completed, the actual template
        can be deployed in Cisco DNA Center.
        :param comments: Comments for the commit action
            type: str
            required: no
            default: ''
        :return: Template object
        """
        body = {'templateId': self.template_id, 'comments': comments}
        url = '%s%s%s' % (self.dnac.url, self.resource,
                          TEMPLATE_VERSION_PATH[self.dnac.version])
        results, status = self.crud.post(url,
                                         headers=self.dnac.hdrs,
                                         body=json.dumps(body),
                                         verify=self.verify,
                                         timeout=timeout)
        if status != ACCEPTED:
            raise DnacApiError(MODULE, 'version_template',
                               REQUEST_NOT_ACCEPTED, url, ACCEPTED, status,
                               ERROR_MSGS[status], '')

        # check the tasks' results
        task = Task(self.dnac, results['response']['taskId'])
        task.get_task_results()
        if task.is_error:
            raise DnacApiError(MODULE, 'version_template',
                               TEMPLATE_VERSION_FAILED, '', '', '', '',
                               task.failure_reason)

        # version succeeded - reload the template and its versions
        return self.load_template(self.name)
Esempio n. 3
0
 def add_project(self, project):
     """
     Adds a project to Cisco DNA Center
     :param project: The project data represented as a dict
     :return: Project object
     """
     # add the project to Cisco DNA Center
     url = '%s%s' % (self.dnac.url, self.resource)
     self.__clean_project__(project)
     body = json.dumps(project)
     results, status = self.crud.post(url,
                                      headers=self.dnac.hdrs,
                                      body=body,
                                      verify=self.verify,
                                      timeout=self.timeout)
     if status != ACCEPTED:
         raise DnacApiError(
             MODULE, 'import_project', REQUEST_NOT_ACCEPTED, url, ACCEPTED, status, ERROR_MSGS[status], ''
         )
     # check the tasks' results
     task = Task(self.dnac, results['response']['taskId'])
     task.get_task_results()
     if task.is_error:
         raise DnacApiError(MODULE, 'import_project', PROJECT_IMPORT_FAILED, '', '', '', '', task.failure_reason)
     # import succeeded; create a new Project object, add it to Dnac and return it
     return Project(self.dnac, project['name'])
Esempio n. 4
0
 def delete(self):
     """
     Removes the Version object from Cisco DNA Center as well as from the program's Dnac object.
     :return: None
     """
     url = self.dnac.url + self.resource
     results, status = self.crud.delete(url, headers=self.dnac.hdrs)
     if status != OK:
         raise DnacApiError(MODULE, 'delete', REQUEST_NOT_OK, url, OK, status, ERROR_MSGS[status], '')
     task = Task(self.dnac, results['response']['taskId'])
     task.get_task_results()
     if task.is_error:
         raise DnacApiError(MODULE, 'delete', task.progress, '', '', '', task.failure_reason, '')
     else:
         # remove self from Dnac.api{}
         del self.dnac.api[self.name]
Esempio n. 5
0
 def add_new_template(self, template, project, timeout=5):
     """
     Creates a new template in Cisco DNA Center and assigns it to the project provided.
     :param template: The template information constructed from a json formatted string
         type: dict
         required: yes
         default: None
     :param project: A reference to the project to which the template should be assigned
         type: Project object
         required: yes
         default: None
     :return: Template object
     """
     # ensure the template is correctly formatted
     self.__is_versioned_template__(template)
     # prepare the template for import
     template = self.__prepare_template__(template)
     # add the template into DNA Center
     url = '%s%s/%s/template' % (self.dnac.url,
                                 PROJECT_RESOURCE_PATH[self.dnac.version],
                                 project.project_id)
     body = json.dumps(template)
     results, status = self.crud.post(url,
                                      headers=self.dnac.hdrs,
                                      body=body,
                                      verify=self.verify,
                                      timeout=timeout)
     if status != ACCEPTED:
         if status == _500_:
             raise DnacApiError(MODULE, 'add_new_template',
                                REQUEST_NOT_ACCEPTED, url, ACCEPTED, status,
                                ERROR_MSGS[status], TEMPLATE_ALREADY_EXISTS)
         else:
             raise DnacApiError(MODULE, 'add_new_template',
                                REQUEST_NOT_ACCEPTED, url, ACCEPTED, status,
                                ERROR_MSGS[status], '')
     # check the tasks' results
     task = Task(self.dnac, results['response']['taskId'])
     task.get_task_results()
     if task.is_error:
         raise DnacApiError(MODULE, 'add_new_template',
                            TEMPLATE_IMPORT_FAILED, '', '', '', '',
                            task.failure_reason)
     # import succeeded; reload the project and return the new template
     project.load_project(project.name)
     return Template(self.dnac, template['name'])
Esempio n. 6
0
    def run_sync(self, wait=3):
        """
        runSync issues the commands set in the CommandRunner and waits
        for their completion.  It performs this action by creating a
        Task object and then checks the task's state periodically
        according to the wait time (seconds) passed as an argument.
        If no wait time is given, it checks every three seconds.

        When the task finishes, the Task object will have also loaded
        the task's results, which can be immediately accessed via the
        CommandRunner instance (cmd.task.file.results) or from
        the function's return value (results = cmd.runSync()).

        Parameters:
            wait: The time to wait before checking the results.
                type: int
                default: 3
                required: no

        Return Values:
            list: The command set's output

        Usage:
            d = Dnac()
            cmd = CommandRunner(d, 'aCmdName')
            results = cmd.runSync(wait=10)
        """
        url = self.dnac.url + self.resource
        results, status = self.crud.post(url,
                                         headers=self.dnac.hdrs,
                                         body=self.__cmds,
                                         verify=self.verify,
                                         timeout=self.timeout)
        if status != ACCEPTED:
            DnacApiError(MODULE, 'run', REQUEST_NOT_ACCEPTED, url, ACCEPTED,
                         status, ERROR_MSGS[status], str(results))
        task_id = results['response']['taskId']
        self.__task = Task(self.dnac, task_id)
        self.__task.check_task()
        while self.__task.progress == TASK_CREATION:
            time.sleep(wait)
            self.__task.check_task()
        return self.__task.file.results
Esempio n. 7
0
 def add_version(self, version, timeout=5):
     """
     Creates a new version of an existing template.
     :param version: The new version to be added to Cisco DNAC
         type: dict constructed from a json formatted file
         required: yes
         default: None
     :return: Template object
     """
     # ensure the template is correctly formatted
     self.__is_versioned_template__(version)
     # check if the template associated with the new version is already in Dnac
     if version['name'] not in self.dnac.api:
         # if not, throw an error
         raise DnacApiError(MODULE, 'add_version',
                            '%s %s' % (TEMPLATE_NOT_FOUND, version['name']),
                            '', '', '', '', CALL_ADD_NEW_TEMPLATE)
     else:
         # if so, save a pointer to it
         template = self.dnac.api[version['name']]
     # prepare the new version
     self.__prepare_version__(version, template)
     # add the new version to DNAC
     url = '%s%s' % (self.dnac.url,
                     TEMPLATE_RESOURCE_PATH[self.dnac.version])
     body = json.dumps(version)
     results, status = self.crud.put(url,
                                     headers=self.dnac.hdrs,
                                     body=body,
                                     verify=self.verify,
                                     timeout=timeout)
     if status != ACCEPTED:
         raise DnacApiError(MODULE, 'add_version', REQUEST_NOT_ACCEPTED,
                            url, ACCEPTED, status, ERROR_MSGS[status], '')
     # check the tasks' results
     task = Task(self.dnac, results['response']['taskId'])
     task.get_task_results()
     if task.is_error:
         raise DnacApiError(MODULE, 'add_version', TEMPLATE_IMPORT_FAILED,
                            '', '', '', '', task.failure_reason)
     # import succeeded; reload the template
     return template.load_template(version['name'])
Esempio n. 8
0
 def delete_config_file(self, file_id):
     """
     Removes the specified file, given by its UUID, from Cisco DNAC and from the Version instance.
     :param file_id: str
     :return: None
     """
     url = '%s%s/%s/%s' % (self.dnac.url, self.resource, CONFIG_FILE_SUB_RESOURCE_PATH[self.dnac.version], file_id)
     results, status = self.crud.delete(url, headers=self.dnac.hdrs)
     if status != OK:
         raise DnacApiError(MODULE, 'delete_config', REQUEST_NOT_OK, url, OK, status, ERROR_MSGS[status], '')
     task = Task(self.dnac, results['response']['taskId'])
     task.get_task_results()
     if task.is_error:
         raise DnacApiError(MODULE, 'delete_config', task.progress, '', '', '', task.failure_reason, '')
     else:
         for config_file_type, config_file in self.__config_files.items():
             if file_id == config_file.id:
                 del self.__config_files[config_file_type]
                 break
         del self.dnac.api['file_%s' % file_id]
Esempio n. 9
0
class CommandRunner(DnacApi):
    """
    The CommandRunner class provides the interface for running CLI commands
    on DNA Center.  Note that the command runner API only allows read-only
    commands, i.e. show commands.

    Command sets must be formatted as a dictionary with two lists.  The
    first item uses "commands" as its key and then has a list of the
    actual CLI commands to run.  The second value's key is "deviceUuids"
    and its values are the device IDs where the commands will be run.
    CommandRunner provides two functions to help produce the dictionary
    used as the API call's body: formatCmd and formatCmds.

    To execute the commands, CommandRunner provdes two different methods.
    run() issues the commands but does not wait for the task to complete.
    runSync() on the other hand, waits for the task to finish and then
    collects the results.

    Attributes:
        dnac: A pointer to the Dnac object containing the CommandRunner instance.
            type: Dnac object
            default: none
            scope: protected
        name: A user-friendly name for accessing the CommandRunner object in a Dnac.api{}.
            type: str
            default: none
            scope: protected
        task: A Task object associated with the commands being run.
            type: Task object
            default: none
            scope: protected
        cmds: The CLI commands to be run on the target devices.
            type: dict
            default: none
            scope: public
        resource: The URI for running commands within Cisco DNAC.
            type: str
            default: Cisco DNA Center version dependent
            scope: protected
        verify: A flag indicating whether or not to verify Cisco DNA Center's certificate.
            type: bool
            default: False
            scope: protected
        timeout: The number of seconds to wait for Cisco DNAC to respond before timing out.
            type: int
            default: 5
            scope: protected

    Usage:
        d = Dnac()
        cmds = {'commands': ['show version', 'show module'],
                'deviceUuids': ['<switch>', '<router>]}
        cmd = CommandRunner(d, "aName", cmds=cmds)
        progress = cmd.run()
        results = cmd.runSync()
    """
    def __init__(self, dnac, name, cmds=None, verify=False, timeout=5):
        """
        The __init__ method creates a CommandRunner object.  As with all
        classes that inherit from DnacApi, a minimum of a Dnac container
        and a name must be given.  Optionally, a dictionary of the CLI
        commands to run and the UUIDs of devices to run them on may
        be specified.

        Parameters:
            dnac: A reference to the containing Dnac object.
                type: Dnac object
                default: none
                required: yes
            name: A user friendly name for finding this object in a Dnac
                  instance.
                type: str
                default: none
                required: yes
            cmds: A dict with the commands and target devices.
                type: dict
                default: none
                required: no
            verify: A flag used to check Cisco DNAC's certificate.
                type: boolean
                default: False
                required: no
            timeout: The number of seconds to wait for Cisco DNAC's
                     response.
                type: int
                default: 5
                required: no

        Return Values:
            CommandRunner object: The newly constructed CommandRunner

        Usage:
            d = Dnac()
            cmds = {'commands': ['show version', 'show module'],
                    'deviceUuids': ['<switch>', '<router>]}
            cmd = CommandRunner(d, "aName", cmds=cmds)
        """
        # check Cisco DNA Center's version and set the resourece path
        if cmds is None:
            cmds = {}
        if dnac.version in SUPPORTED_DNAC_VERSIONS:
            path = COMMANDRUNNER_RESOURCE_PATH[dnac.version]
        else:
            raise DnacError('__init__: %s: %s' %
                            (UNSUPPORTED_DNAC_VERSION, dnac.version))
        # setup the attributes
        self.__cmds = cmds  # commands to run
        self.__task = None  # Task object created after running cmds
        super(CommandRunner, self).__init__(dnac,
                                            name,
                                            resource=path,
                                            verify=verify,
                                            timeout=timeout)

# end __init__()

    @property
    def cmds(self):
        """
        Get method cmds returns the __cmds body to be sent to Cisco DNAC.

        Parameters:
            none

        Return Values:
            dict: A list of CLI commands and the devices on which to
                  execute them.

        Usage:
            d = Dnac()
            cmds = {'commands': ['show version', 'show module'],
                    'deviceUuids': ['<switch>', '<router>]}
            cmd = CommandRunner(d, "aName", cmds=cmds)
            pprint.PrettyPrint(cmd.cmds)
        """
        return self.__cmds

# end cmds getter

    @cmds.setter
    def cmds(self, cmds):
        """
        Method cmds sets its __cmds attribute to the dictionary of
            commands given.

        Parameters:
            cmds: A dict of commands and device UUIDs to run the
                      commands against.
                    type: dict
                    default: None
                    required: Yes

        Return Values:
            None

        Usage:
            d = Dnac()
            cmd = CommandRunner(d, 'aName')
            cmds = ['show version', 'show module', 'show proc cpu']
            cmd.cmds = cmds
        """
        self.__cmds = cmds

# end cmds setter

    @property
    def task(self):
        """
        The task get function returns the Task object stored in __task.

        Parameters:
            none

        Return Values:
            Task object: The task associated with the CommandRunner
            instance.

        Usage:
            d = Dnac()
            cmd = CommandRunner(d, 'aName')
            cliCmd = 'show module'
            switch = '<switch's UUID>'
            cmd.formatCmd(cliCmd, switch)
            cmd.run()
            task = cmd.task
        """
        return self.__task

# end cmds getter

    def format_cmd(self, cmd, uuid):
        """
        The formatCmd method takes a single CLI command and runs it against
        the UUID of a network device in Cisco DNA Center.  It converts the
        command and the UUID into a dict stored in the __cmds attribute
        and returns __cmds' value.

        Parameters:
            cmd: A CLI command.
                type: str
                default: none
                required: yes
            uuid: A network device UUID.
                type: str
                default: none
                required: yes

        Return Values:
            dict: The command instructions used as the body for making
                  an API call to Cisco DNAC's command runner.

        Usage:
            d = Dnac()
            cmd = 'show version'
            uuid = '<switch_uuid>'
            cmd = CommandRunner(d, 'aName')
            cmd.format_cmd(cmd, uuid)
        """
        c = [cmd]
        u = [uuid]
        cmds = {'commands': c, 'deviceUuids': u}
        self.__cmds = json.dumps(cmds)
        return self.__cmds

# end format_cmd()

    def format_cmds(self, cmd_list, uuid_list):
        """
        The format_cmds method accepts a list of CLI commands to run against
        a list of UUIDs for the target network devices in Cisco DNA Center.
        It converts the two lists into a dict stored in the __cmds attribute
        and returns __cmds' value.

        Parameters:
            cmd_list: A list of CLI commands.
                type: list of str
                default: none
                required: yes
            uuid_list: A list of network device UUIDs.
                type: list of str
                default: none
                required: yes

        Return Values:
            dict: The command instructions used as the body for making
                  an API call to Cisco DNAC's command runner.

        Usage:
            d = Dnac()
            cmds = ['show version', 'show ip interface brief']
            uuids = ['<switch_uuid>', '<router_uuid>']
            cmds = CommandRunner(d, 'aName')
            cmds.format_cmds(cmds, uuids)
        """
        cmds = {'commands': cmd_list, 'deviceUuids': uuid_list}
        self.__cmds = json.dumps(cmds)
        return self.__cmds

# end format_cmds()

    def run(self):
        """
        Method run instructs Cisco DNAC to execute the command set stored in
        the CommandRunner object.  It does not wait for the task to
        complete on Cisco DNA Center.  It does, however, create a new Task
        object, saves it in the __task attribute, checks the task, and
        then returns the task's status.  See the task.py module for
        valid task states.  When using this function, the programmer
        must handle task monitoring.

        Parameters:
            none

        Return Values:
            str: The current state of the command's progress.

        Usage:
            d = Dnac()
            cmd = CommandRunner(d, 'aName')
            cmdState = cmd.run()
        """
        url = self.dnac.url + self.resource
        results, status = self.crud.post(url,
                                         headers=self.dnac.hdrs,
                                         body=self.__cmds,
                                         verify=self.verify,
                                         timeout=self.timeout)
        if status != ACCEPTED:
            raise DnacApiError(MODULE, 'run', REQUEST_NOT_ACCEPTED, url,
                               ACCEPTED, status, ERROR_MSGS[status],
                               str(results))
        task_id = results['response']['taskId']
        self.__task = Task(self.dnac, task_id)
        return self.__task.check_task()

# end run()

    def run_sync(self, wait=3):
        """
        runSync issues the commands set in the CommandRunner and waits
        for their completion.  It performs this action by creating a
        Task object and then checks the task's state periodically
        according to the wait time (seconds) passed as an argument.
        If no wait time is given, it checks every three seconds.

        When the task finishes, the Task object will have also loaded
        the task's results, which can be immediately accessed via the
        CommandRunner instance (cmd.task.file.results) or from
        the function's return value (results = cmd.runSync()).

        Parameters:
            wait: The time to wait before checking the results.
                type: int
                default: 3
                required: no

        Return Values:
            list: The command set's output

        Usage:
            d = Dnac()
            cmd = CommandRunner(d, 'aCmdName')
            results = cmd.runSync(wait=10)
        """
        url = self.dnac.url + self.resource
        results, status = self.crud.post(url,
                                         headers=self.dnac.hdrs,
                                         body=self.__cmds,
                                         verify=self.verify,
                                         timeout=self.timeout)
        if status != ACCEPTED:
            DnacApiError(MODULE, 'run', REQUEST_NOT_ACCEPTED, url, ACCEPTED,
                         status, ERROR_MSGS[status], str(results))
        task_id = results['response']['taskId']
        self.__task = Task(self.dnac, task_id)
        self.__task.check_task()
        while self.__task.progress == TASK_CREATION:
            time.sleep(wait)
            self.__task.check_task()
        return self.__task.file.results