diff --git a/.travis.yml b/.travis.yml index 32e6929..6784be1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ language: python python: -- 2.7 -- 3.4 -- 3.5 + - 2.7 + - 3.4 + - 3.5 install: -- pip install . -- pip install -r requirements-dev.txt + - pip install tox-travis + - pip install coveralls deploy: provider: pypi @@ -19,8 +19,8 @@ deploy: branch: master script: -- py.test --cov-report= --cov=napalm_nxos test/ -- pylama . + - tox after_success: -- coveralls -- if [ $TRAVIS_TAG ]; then curl -X POST https://readthedocs.org/build/napalm; fi + - coveralls + - if [ $TRAVIS_TAG ]; then curl -X POST https://readthedocs.org/build/napalm; fi + diff --git a/napalm_nxos/nxos.py b/napalm_nxos/nxos.py index 8791219..23d5e31 100644 --- a/napalm_nxos/nxos.py +++ b/napalm_nxos/nxos.py @@ -56,6 +56,7 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.fc = None self.changed = False self.replace_file = None + self.merge_candidate = '' if optional_args is None: optional_args = {} @@ -212,11 +213,12 @@ def load_merge_candidate(self, filename=None, config=None): if not filename and not config: raise MergeConfigException('filename or config param must be provided.') + self.merge_candidate += '\n' # insert one extra line if filename is not None: with open(filename, "r") as f: - self.merge_candidate = f.read() + self.merge_candidate += f.read() else: - self.merge_candidate = config + self.merge_candidate += config def _send_file(self, filename, dest): self.fc = FileCopy(self.device, filename, dst=dest.split('/')[-1]) @@ -261,13 +263,21 @@ def _get_merge_diff(self): if line not in running_lines and line: if line[0].strip() != '!': diff.append(line) - self.merge_candidate = '\n'.join(diff) + return '\n'.join(diff) + # the merge diff is not necessarily what needs to be loaded + # for example under NTP, as the `ntp commit` command might be + # alread configured, it is mandatory to be sent + # otherwise it won't take the new configuration - see #59 + # https://github.com/napalm-automation/napalm-nxos/issues/59 + # therefore this method will return the real diff + # but the merge_candidate will remain unchanged + # previously: self.merge_candidate = '\n'.join(diff) def compare_config(self): if self.loaded: if not self.replace: - self._get_merge_diff() - return self.merge_candidate + return self._get_merge_diff() + # return self.merge_candidate diff = self._get_diff(self.fc.dst) return diff return '' @@ -293,7 +303,7 @@ def _load_config(self): except ConnectionError: # requests will raise an error with verbose warning output return True - except: + except Exception: return False return True @@ -307,6 +317,7 @@ def commit_config(self): else: try: self._commit_merge() + self.merge_candidate = '' # clear the merge buffer except Exception as e: raise MergeConfigException(str(e)) @@ -321,6 +332,8 @@ def _delete_file(self, filename): self.device.show('no terminal dont-ask', raw_text=True) def discard_config(self): + if self.loaded: + self.merge_candidate = '' # clear the buffer if self.loaded and self.replace: try: self._delete_file(self.fc.dst) @@ -812,7 +825,8 @@ def traceroute(self, destination, source=c.TRACEROUTE_SOURCE, ttl=c.TRACEROUTE_TTL, - timeout=c.TRACEROUTE_TIMEOUT): + timeout=c.TRACEROUTE_TIMEOUT, + vrf=c.TRACEROUTE_VRF): _HOP_ENTRY_PROBE = [ '\s+', '(', # beginning of host_name (ip_address) RTT group diff --git a/napalm_nxos/templates/delete_ntp_peers.j2 b/napalm_nxos/templates/delete_ntp_peers.j2 index cee41bf..85f89c7 100644 --- a/napalm_nxos/templates/delete_ntp_peers.j2 +++ b/napalm_nxos/templates/delete_ntp_peers.j2 @@ -1,3 +1,4 @@ {% for peer in peers %} no ntp peer {{peer}} {% endfor %} +ntp commit diff --git a/napalm_nxos/templates/delete_ntp_servers.j2 b/napalm_nxos/templates/delete_ntp_servers.j2 index 38accdf..ed15abf 100644 --- a/napalm_nxos/templates/delete_ntp_servers.j2 +++ b/napalm_nxos/templates/delete_ntp_servers.j2 @@ -1,3 +1,4 @@ {% for server in servers %} no ntp server {{server}} {% endfor %} +ntp commit diff --git a/napalm_nxos/templates/delete_users.j2 b/napalm_nxos/templates/delete_users.j2 new file mode 100644 index 0000000..41e0a37 --- /dev/null +++ b/napalm_nxos/templates/delete_users.j2 @@ -0,0 +1,16 @@ +{%- for user_name, user_details in users.items() %} +{%- if user_details -%} +{%- if user_details.get('sshkeys') %} +{%- for sshkey in user_details.sshkeys %} +no username {{user_name}} sshkey {{ sshkey }} +{%- endfor %} +{%- endif %} +{%- if user_details.get('password') %} +no username {{user_name}} password +{%- endif %} +{%- if user_details.get('level') %} +no username {{user_name}} role priv-{{user_details.level}} +{%- endif %} +{%- endfor %} +{%- else -%} +{%- endif -%} diff --git a/napalm_nxos/templates/set_ntp_peers.j2 b/napalm_nxos/templates/set_ntp_peers.j2 index 1dd886b..57b16ed 100644 --- a/napalm_nxos/templates/set_ntp_peers.j2 +++ b/napalm_nxos/templates/set_ntp_peers.j2 @@ -1,3 +1,4 @@ {% for peer in peers %} ntp peer {{peer}} {% endfor %} +ntp commit diff --git a/napalm_nxos/templates/set_ntp_servers.j2 b/napalm_nxos/templates/set_ntp_servers.j2 index 1cebc15..b4758d2 100644 --- a/napalm_nxos/templates/set_ntp_servers.j2 +++ b/napalm_nxos/templates/set_ntp_servers.j2 @@ -1,3 +1,4 @@ {% for server in servers %} ntp server {{server}} {% endfor %} +ntp commit diff --git a/napalm_nxos/templates/set_users.j2 b/napalm_nxos/templates/set_users.j2 new file mode 100644 index 0000000..c49f783 --- /dev/null +++ b/napalm_nxos/templates/set_users.j2 @@ -0,0 +1,13 @@ +{%- for user_name, user_details in users.items() %} +{%- if user_details.get('sshkeys') %} +{%- for sshkey in user_details.sshkeys %} +username {{user_name}} sshkey {{ sshkey }} +{%- endfor %} +{%- endif %} +{%- if user_details.get('password') %} +username {{user_name}} password 5 {{user_details.password}} +{%- endif %} +{%- if user_details.get('level') %} +username {{user_name}} role priv-{{user_details.level}} +{%- endif %} +{%- endfor %} diff --git a/requirements-dev.txt b/requirements-dev.txt index 6b6a977..f42a250 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,4 +4,6 @@ pytest-cov pytest-json pytest-pythonpath pylama +flake8-import-order -r requirements.txt + diff --git a/setup.cfg b/setup.cfg index 559b516..b946a3e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,15 +1,16 @@ [pylama] linters = mccabe,pep8,pyflakes ignore = D203,C901 +skip = build/*,.tox/* [pylama:pep8] max_line_length = 100 -[tool:pytest] -addopts = --cov=./ -vs +[pytest] +addopts = --cov=napalm_nxos --cov-report term-missing -vs --pylama json_report = report.json jsonapi = true [coverage:run] -include = - napalm_nxos/* +source = napalm_nxos + diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..5ae5d81 --- /dev/null +++ b/tox.ini @@ -0,0 +1,9 @@ +[tox] +envlist = py27,py34,py35 + +[testenv] +deps = + -rrequirements-dev.txt + +commands= + py.test