<commit_before># Copyright 2015 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.

import re
import collections
from lxml.builder import E

from napalm_junos.utils import junos_views
from napalm_base.base import NetworkDriver

from jnpr.junos import Device
from jnpr.junos.utils.config import Config
from jnpr.junos.exception import ConfigLoadError, ConnectTimeoutError
from napalm_base.exceptions import ConnectionException, ReplaceConfigException, MergeConfigException,\
                                   CommandErrorException

from napalm_base.utils import string_parsers


class JunOSDriver(NetworkDriver):

    def __init__(self, hostname, username, password, timeout=60, optional_args=None):
        self.hostname = hostname
        self.username = username
        self.password = password
        self.timeout = timeout
        self.config_replace = False
        self.locked = False

        if optional_args is None:
            optional_args = {}
        self.port = optional_args.get('port', 22)
        self.config_lock = optional_args.get('config_lock', True)

        self.device = Device(hostname, user=username, password=password, port=self.port)

    def open(self):
        try:
            self.device.open()
        except ConnectTimeoutError as cte:
            raise ConnectionException(cte.message)
        self.device.timeout = self.timeout
        self.device.bind(cu=Config)
        if self.config_lock:
            self.lock()

    def close(self):
        if self.config_lock:
            self.unlock()
        self.device.close()

    def lock(self):
        if not self.locked:
            self.device.cu.lock()
            self.locked = True

    def unlock(self):
        if self.locked:
            self.device.cu.unlock()
            self.locked = False

    def _load_candidate(self, filename, config, overwrite):
        if filename is None:
            configuration = config
        else:
            with open(filename) as f:
                configuration = f.read()

        if not self.config_lock:
            # if not locked during connection time
            # will try to lock it if not already aquired
            self.lock()
            # and the device will be locked till first commit/rollback

        try:
            self.device.cu.load(configuration, format='text', overwrite=overwrite)
        except ConfigLoadError as e:
            if self.config_replace:
                raise ReplaceConfigException(e.message)
            else:
                raise MergeConfigException(e.message)

    def load_replace_candidate(self, filename=None, config=None):
        self.config_replace = True
        self._load_candidate(filename, config, True)

    def load_merge_candidate(self, filename=None, config=None):
        self.config_replace = False
        self._load_candidate(filename, config, False)

    def compare_config(self):
        diff = self.device.cu.diff()

        if diff is None:
            return ''
        else:
            return diff.strip()

    def commit_config(self):
        self.device.cu.commit()
        if not self.config_lock:
            self.unlock()

    def discard_config(self):
        self.device.cu.rollback(rb_id=0)
        if not self.config_lock:
            self.unlock()

    def rollback(self):
        self.device.cu.rollback(rb_id=1)
        self.commit_config()


    # perhaps both should be moved in napalm_base.helpers at some point
    @staticmethod
    def _find_txt(xml_tree, path, default = ''):
        try:
            return xml_tree.find(path).text.strip()
        except Exception:
            return default


    @staticmethod
    def _convert(to, who, default = u''):
        if who is None:
            return default
        try:
            return to(who)
        except:
            return default


    def get_facts(self):

        output = self.device.facts

        uptime = 0
        if 'RE0' in output:
            uptime = output['RE0']['up_time']

        interfaces = junos_views.junos_iface_table(self.device)
        interfaces.get()
        interface_list = interfaces.keys()

        return {
            'vendor': u'Juniper',
            'model': unicode(output['model']),
            'serial_number': unicode(output['serialnumber']),
            'os_version': unicode(output['version']),
            'hostname': unicode(output['hostname']),
            'fqdn': unicode(output['fqdn']),
            'uptime': string_parsers.convert_uptime_string_seconds(uptime),
            'interface_list': interface_list
        }

    def get_interfaces(self):

        # init result dict
        result = {}

        interfaces = junos_views.junos_iface_table(self.device)
        interfaces.get()

        # convert all the tuples to our pre-defined dict structure<commit_msg>Make default uptime str instead of int since convert_uptime_string_seconds() expects a str<commit_after># Copyright 2015 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.

import re
import collections
from lxml.builder import E

from napalm_junos.utils import junos_views
from napalm_base.base import NetworkDriver

from jnpr.junos import Device
from jnpr.junos.utils.config import Config
from jnpr.junos.exception import ConfigLoadError, ConnectTimeoutError
from napalm_base.exceptions import ConnectionException, ReplaceConfigException, MergeConfigException,\
                                   CommandErrorException

from napalm_base.utils import string_parsers


class JunOSDriver(NetworkDriver):

    def __init__(self, hostname, username, password, timeout=60, optional_args=None):
        self.hostname = hostname
        self.username = username
        self.password = password
        self.timeout = timeout
        self.config_replace = False
        self.locked = False

        if optional_args is None:
            optional_args = {}
        self.port = optional_args.get('port', 22)
        self.config_lock = optional_args.get('config_lock', True)

        self.device = Device(hostname, user=username, password=password, port=self.port)

    def open(self):
        try:
            self.device.open()
        except ConnectTimeoutError as cte:
            raise ConnectionException(cte.message)
        self.device.timeout = self.timeout
        self.device.bind(cu=Config)
        if self.config_lock:
            self.lock()

    def close(self):
        if self.config_lock:
            self.unlock()
        self.device.close()

    def lock(self):
        if not self.locked:
            self.device.cu.lock()
            self.locked = True

    def unlock(self):
        if self.locked:
            self.device.cu.unlock()
            self.locked = False

    def _load_candidate(self, filename, config, overwrite):
        if filename is None:
            configuration = config
        else:
            with open(filename) as f:
                configuration = f.read()

        if not self.config_lock:
            # if not locked during connection time
            # will try to lock it if not already aquired
            self.lock()
            # and the device will be locked till first commit/rollback

        try:
            self.device.cu.load(configuration, format='text', overwrite=overwrite)
        except ConfigLoadError as e:
            if self.config_replace:
                raise ReplaceConfigException(e.message)
            else:
                raise MergeConfigException(e.message)

    def load_replace_candidate(self, filename=None, config=None):
        self.config_replace = True
        self._load_candidate(filename, config, True)

    def load_merge_candidate(self, filename=None, config=None):
        self.config_replace = False
        self._load_candidate(filename, config, False)

    def compare_config(self):
        diff = self.device.cu.diff()

        if diff is None:
            return ''
        else:
            return diff.strip()

    def commit_config(self):
        self.device.cu.commit()
        if not self.config_lock:
            self.unlock()

    def discard_config(self):
        self.device.cu.rollback(rb_id=0)
        if not self.config_lock:
            self.unlock()

    def rollback(self):
        self.device.cu.rollback(rb_id=1)
        self.commit_config()


    # perhaps both should be moved in napalm_base.helpers at some point
    @staticmethod
    def _find_txt(xml_tree, path, default = ''):
        try:
            return xml_tree.find(path).text.strip()
        except Exception:
            return default


    @staticmethod
    def _convert(to, who, default = u''):
        if who is None:
            return default
        try:
            return to(who)
        except:
            return default


    def get_facts(self):

        output = self.device.facts

        uptime = '0'
        if 'RE0' in output:
            uptime = output['RE0']['up_time']

        interfaces = junos_views.junos_iface_table(self.device)
        interfaces.get()
        interface_list = interfaces.keys()

        return {
            'vendor': u'Juniper',
            'model': unicode(output['model']),
            'serial_number': unicode(output['serialnumber']),
            'os_version': unicode(output['version']),
            'hostname': unicode(output['hostname']),
            'fqdn': unicode(output['fqdn']),
            'uptime': string_parsers.convert_uptime_string_seconds(uptime),
            'interface_list': interface_list
        }

    def get_interfaces(self):

        # init result dict
        result = {}

        interfaces = junos_views.junos_iface_table(self.device)
        interfaces.get()

        # convert all the tuples to our pre-defined dict structure
{'fraction_non_alphanumeric': 0.08491702975804209, 'fraction_numerical': 0.0031519421525910817, 'mean_word_length': 2.2890243902439025, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6679709', 'n_tokens_mistral': 2989, 'n_tokens_neox': 2862, 'n_words': 824}