[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