[Python-modules-commits] [pyeos] 01/04: Imported Upstream version 0.63

Vincent Bernat bernat at moszumanska.debian.org
Fri May 27 18:52:55 UTC 2016


This is an automated email from the git hooks/post-receive script.

bernat pushed a commit to branch master
in repository pyeos.

commit b30721f7998a1fffbe5f347dc12c6b0d996d0d84
Author: Vincent Bernat <bernat at debian.org>
Date:   Fri May 27 20:47:35 2016 +0200

    Imported Upstream version 0.63
---
 MANIFEST.in                         |   1 +
 PKG-INFO                            |  12 ++
 pyEOS.egg-info/PKG-INFO             |  12 ++
 pyEOS.egg-info/SOURCES.txt          |  12 ++
 pyEOS.egg-info/dependency_links.txt |   1 +
 pyEOS.egg-info/requires.txt         |   1 +
 pyEOS.egg-info/top_level.txt        |   1 +
 pyEOS/__init__.py                   |  15 +++
 pyEOS/eos.py                        | 227 ++++++++++++++++++++++++++++++++++++
 pyEOS/exceptions.py                 |  25 ++++
 requirements.txt                    |   1 +
 setup.cfg                           |   8 ++
 setup.py                            |  29 +++++
 13 files changed, 345 insertions(+)

diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..f9bd145
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include requirements.txt
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..5d2b065
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 1.1
+Name: pyEOS
+Version: 0.63
+Summary: Python API to interact with network devices running EOS
+Home-page: https://github.com/spotify/pyeos/
+Author: David Barroso
+Author-email: dbarroso at spotify.com
+License: UNKNOWN
+Download-URL: https://github.com/spotify/pyeos/tarball/0.63
+Description: UNKNOWN
+Keywords: EOS,networking
+Platform: UNKNOWN
diff --git a/pyEOS.egg-info/PKG-INFO b/pyEOS.egg-info/PKG-INFO
new file mode 100644
index 0000000..5d2b065
--- /dev/null
+++ b/pyEOS.egg-info/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 1.1
+Name: pyEOS
+Version: 0.63
+Summary: Python API to interact with network devices running EOS
+Home-page: https://github.com/spotify/pyeos/
+Author: David Barroso
+Author-email: dbarroso at spotify.com
+License: UNKNOWN
+Download-URL: https://github.com/spotify/pyeos/tarball/0.63
+Description: UNKNOWN
+Keywords: EOS,networking
+Platform: UNKNOWN
diff --git a/pyEOS.egg-info/SOURCES.txt b/pyEOS.egg-info/SOURCES.txt
new file mode 100644
index 0000000..7ed424c
--- /dev/null
+++ b/pyEOS.egg-info/SOURCES.txt
@@ -0,0 +1,12 @@
+MANIFEST.in
+requirements.txt
+setup.cfg
+setup.py
+pyEOS/__init__.py
+pyEOS/eos.py
+pyEOS/exceptions.py
+pyEOS.egg-info/PKG-INFO
+pyEOS.egg-info/SOURCES.txt
+pyEOS.egg-info/dependency_links.txt
+pyEOS.egg-info/requires.txt
+pyEOS.egg-info/top_level.txt
\ No newline at end of file
diff --git a/pyEOS.egg-info/dependency_links.txt b/pyEOS.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pyEOS.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/pyEOS.egg-info/requires.txt b/pyEOS.egg-info/requires.txt
new file mode 100644
index 0000000..1410b2f
--- /dev/null
+++ b/pyEOS.egg-info/requires.txt
@@ -0,0 +1 @@
+jsonrpclib
diff --git a/pyEOS.egg-info/top_level.txt b/pyEOS.egg-info/top_level.txt
new file mode 100644
index 0000000..8411016
--- /dev/null
+++ b/pyEOS.egg-info/top_level.txt
@@ -0,0 +1 @@
+pyEOS
diff --git a/pyEOS/__init__.py b/pyEOS/__init__.py
new file mode 100644
index 0000000..27f7cb8
--- /dev/null
+++ b/pyEOS/__init__.py
@@ -0,0 +1,15 @@
+# Copyright 2014 Spotify AB. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from eos import EOS
\ No newline at end of file
diff --git a/pyEOS/eos.py b/pyEOS/eos.py
new file mode 100644
index 0000000..7046cdc
--- /dev/null
+++ b/pyEOS/eos.py
@@ -0,0 +1,227 @@
+# Copyright 2014 Spotify AB. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from jsonrpclib import Server
+from jsonrpclib import ProtocolError
+
+import exceptions
+
+
+class EOS:
+    def __init__(self, hostname, username, password, use_ssl=True):
+        """
+        Represents a device running EOS.
+
+        The object will contain the following interesting attributes:
+
+        * **running_config** - The configuration retrieved from the device using the method load_running_config
+        * **candidate_config** - The configuration we desire for the device. Can be populated using the method load_candidate_config
+
+        :param hostname: IP or FQDN of the device you want to connect to
+        :param username: Username
+        :param password: Password
+        :param use_ssl: If set you True we will connect to the eAPI using https, otherwise http will be used
+        """
+        self.hostname = hostname
+        self.username = username
+        self.device = None
+        self.password = password
+        self.use_ssl = use_ssl
+        self.candidate_config = None
+        self.original_config = None
+
+    def __getattr__(self, item):
+        def wrapper(*args, **kwargs):
+            pipe = kwargs.pop('pipe', None)
+
+            if pipe is None:
+                cmd = [item.replace('_', ' ')]
+            else:
+                cmd = ['{} | {}'.format(item.replace('_', ' '), pipe)]
+            return self.run_commands(cmd, **kwargs)[1]
+
+        if item.startswith('show'):
+            return wrapper
+        else:
+            raise AttributeError("type object '%s' has no attribute '%s'" % (self.__class__.__name__, item))
+
+    @staticmethod
+    def _load_file(filename):
+        string = ''
+        with open(filename, 'r') as f:
+            for line in f.readlines():
+                if line.strip() != '':
+                    string += '{}\n'.format(line.strip())
+
+            return string
+
+    def open(self):
+        """
+        Opens the connection with the device.
+        """
+        if self.use_ssl:
+            url = 'https://%s:%s@%s/command-api' % (self.username, self.password, self.hostname)
+        else:
+            url = 'http://%s:%s@%s/command-api' % (self.username, self.password, self.hostname)
+
+        self.device = Server(url)
+
+    def run_commands(self, commands, version=1, auto_format=False, format='json', timestamps=True):
+        """
+        This method will run as many commands as you want. The 'enable' command will be prepended automatically so you
+        don't have to worry about that.
+
+        :param commands: List of commands you want to run
+        :param version: Version of the eAPI you want to connect to. By default is 1.
+        :param auto_format: If set to True API calls not supporting returning JSON messages will be converted automatically to text. By default is False.
+        :param format: Format you want to get; 'json' or 'text'. By default is json. This will trigger a CommandUnconverted exception if set to 'json' and auto_format is set to False. It will return text if set to 'json' but auto_format is set to True.
+        :param timestamps: This will return some useful information like when was the command executed and how long it took.
+
+        """
+
+        if 'enable' is not commands[0]:
+            commands.insert(0, 'enable')
+
+        if auto_format:
+            format = 'json'
+
+        try:
+            result = self.device.runCmds(
+                version=version,
+                cmds=commands,
+                format=format,
+                timestamps=timestamps,
+            )
+        except ProtocolError as e:
+            code = e[0][0]
+            error = e[0][1]
+
+            if code == 1003:
+                # code 1003 means the command is not yet converted to json
+                if auto_format:
+                    result = self.device.runCmds(
+                        version=version,
+                        cmds=commands,
+                        format='text',
+                        timestamps=timestamps
+                    )
+                else:
+                    raise exceptions.CommandUnconverted(error)
+            # code -32602 means "Unexpected parameter 'timestamps' for method 'runCmds' provided"
+            elif code == -32602:
+                result = self.device.runCmds(
+                    version=version,
+                    cmds=commands,
+                    format=format
+                )
+            elif code == 1002:
+                # code 1002 means the command was wrong
+                raise exceptions.CommandError(error)
+            elif code == 1000:
+                # code 1000 means a command is wrong when doing a "config  replace"
+                raise exceptions.ConfigReplaceError(e)
+            else:
+                raise exceptions.UnknownError((code, error))
+
+        return result
+
+    def close(self):
+        """
+        Dummy, method. Today it does not do anything but it would be interesting to use it to fake closing a connection.
+
+        """
+        pass
+
+    def get_config(self, format='json'):
+        """
+
+        :param format: Either 'json' or 'text'
+        :return: The running configuration of the device.
+        """
+        if format == 'json':
+            return self.run_commands(['sh running-config'])[1]['cmds']
+        elif format == 'text':
+            return self.run_commands(['sh running-config'], format='text')[1]['output']
+
+    def load_candidate_config(self, filename=None, config=None):
+        """
+        Populates the attribute candidate_config with the desired configuration. You can populate it from a file or
+        from a string. If you send both a filename and a string containing the configuration, the file takes precedence.
+
+        :param filename: Path to the file containing the desired configuration. By default is None.
+        :param config: String containing the desired configuration.
+        """
+
+        if filename is not None:
+            self.candidate_config = self._load_file(filename)
+        else:
+            self.candidate_config = config
+
+    def compare_config(self, session=None):
+        """
+
+        :return: A string showing the difference between the running_config and the candidate_config. The running_config is
+            loaded automatically just before doing the comparison so there is no neeed for you to do it.
+        """
+
+        # We get the config in text format because you get better printability by parsing and using an OrderedDict
+
+        cmds = self.candidate_config.splitlines()
+
+        cmds.insert(0, 'configure session pyeos-diff')
+        cmds.insert(1, 'rollback clean-config')
+
+        self.run_commands(cmds)
+
+        diff = self.run_commands(['show session-config named pyeos-diff diffs'], format='text')
+
+        self.run_commands(['configure session pyeos-diff', 'abort'])
+
+        return diff[1]['output'][:-1]
+
+    def replace_config(self, config=None, force=False):
+        """
+        Applies the configuration changes on the device. You can either commit the changes on the candidate_config
+        attribute or you can send the desired configuration as a string. Note that the current configuration of the
+        device is replaced with the new configuration.
+
+        :param config: String containing the desired configuration. If set to None the candidate_config will be used
+        :param force: If set to False we rollback changes if we detect a config error.
+
+        """
+        if config is None:
+            config = self.candidate_config
+
+        if force:
+            force_text = 'ignore-errors'
+        else:
+            force_text = ''
+
+        body = {
+            'cmd': 'configure replace terminal: %s' % force_text,
+            'input': config
+        }
+        self.original_config = self.get_config(format='text')
+        result = self.run_commands([body])
+
+        if 'Invalid' not in result[1]['messages'][0]:
+            return result
+        else:
+            raise exceptions.CommandError(result[1]['messages'][0])
+
+    def rollback(self):
+        """
+        If used after a commit, the configuration will be reverted to the previous state.
+        """
+        return self.replace_config(config=self.original_config, force=True)
diff --git a/pyEOS/exceptions.py b/pyEOS/exceptions.py
new file mode 100644
index 0000000..f5e5f02
--- /dev/null
+++ b/pyEOS/exceptions.py
@@ -0,0 +1,25 @@
+# Copyright 2014 Spotify AB. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+class ConfigReplaceError(Exception):
+    pass
+
+class CommandUnconverted(Exception):
+    pass
+
+class CommandError(Exception):
+    pass
+
+class UnknownError(Exception):
+    pass
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..895a9dd
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+jsonrpclib
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..8c9157d
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,8 @@
+[metadata]
+description-file = README.md
+
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..8f1a9f8
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,29 @@
+from setuptools import setup, find_packages
+from pip.req import parse_requirements
+import uuid
+
+
+# parse_requirements() returns generator of pip.req.InstallRequirement objects
+install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1())
+
+# reqs is a list of requirement
+# e.g. ['django==1.5.1', 'mezzanine==1.4.6']
+reqs = [str(ir.req) for ir in install_reqs]
+
+version = '0.63'
+
+setup(
+    name='pyEOS',
+    version=version,
+    py_modules=['pyEOS'],
+    packages=find_packages(),
+    install_requires=reqs,
+    include_package_data=True,
+    description = 'Python API to interact with network devices running EOS',
+    author = 'David Barroso',
+    author_email = 'dbarroso at spotify.com',
+    url = 'https://github.com/spotify/pyeos/', # use the URL to the github repo
+    download_url = 'https://github.com/spotify/pyeos/tarball/%s' % version,
+    keywords = ['EOS', 'networking'],
+    classifiers = [],
+)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pyeos.git



More information about the Python-modules-commits mailing list