<commit_before># Copyright (C) 2013 IBM Corporation
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
#
# Author: <NAME> (<EMAIL>)

import paramiko
from iplugin import IStorageAreaNetwork
from common import LsmError, ErrorNumber, uri_parse
from version import VERSION
from data import Volume, Initiator, FileSystem, Snapshot, \
    AccessGroup, System, Capabilities, Pool


def handle_ssh_errors(method):
    def ssh_wrapper(*args, **kwargs):
        try:
            return method(*args, **kwargs)
        except paramiko.SSHException as sshe:
            raise LsmError(ErrorNumber.TRANSPORT_COMMUNICATION, str(sshe))

    return ssh_wrapper


class V7kError(Exception):
    """
    Class represents a v7k cli bad return code
    """

    def __init__(self, errno, reason, *args, **kwargs):
        Exception.__init__(self, *args, **kwargs)
        self.errno = errno
        self.reason = reason


# NOTE: v7k cli doc doesn't list the possible error codes per cli.
# Thus do very generic and basic error handling for now.
# Just pass the error msg & code returned by the array back to lsm.
def handle_v7k_errors(method):
    def v7k_wrapper(*args, **kwargs):
        try:
            return method(*args, **kwargs)
        except V7kError as ve:
            msg = ve.reason + " (vendor error code= " + str(ve.errno) + ")"
            raise LsmError(ErrorNumber.PLUGIN_ERROR, msg)

    return v7k_wrapper


# A lite weight sshclient
class SSHClient():

    @handle_ssh_errors
    def __init__(self, hostname, login, passwd, conn_timeout=30):
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        try:
            self.ssh.connect(hostname, username=login, password=<PASSWORD>,
                             timeout=conn_timeout)
        except Exception as e:
            msg = ("Error while connecting via ssh to host %s : %s") % (hostname, e)
            raise paramiko.SSHException(msg)

    @handle_v7k_errors
    def execute(self, command, check_exit_code=True):
        stdin_strm, stdout_strm, stderr_strm = self.ssh.exec_command(command)

        stdin_strm.close()

        stdout_channel = stdout_strm.channel
        exit_code = stdout_channel.recv_exit_status()
        stdout_channel.close()

        stdout = stdout_strm.read()
        stdout_strm.close()

        stderr = stderr_strm.read()
        stderr_strm.close()

        if check_exit_code and exit_code != 0:
            errList = stderr.split(' ', 1)

            if exit_code == 127:
                # command not found error
                errno = exit_code
            else:
                # other errors
                errno = errList[0]

            reason = errList[1]

            raise V7kError(errno, reason)

        return (exit_code, stdout, stderr)

    @handle_ssh_errors
    def close(self):
        self.ssh.close()


# IBM V7000 storage lsm plugin

# *** lsm -- IBM V7000 terminology mapping ***
# volume -- v7k volume (aka vdisk)
# initiator -- host
# access group --  NA
# NA -- I/O group
# pool -- mdisk group
# volume-child dep -- ~fcmap and other maps if any
# job -- cli that can be invoked in async mode

class IbmV7k(IStorageAreaNetwork):

    def __init__(self):
        self.sys_info = None
        self.ssh = None

    def _execute_command_and_parse_detailed(self, ssh_cmd):
        exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)

        cmd_output = {}
        for line in stdout.split('\n'):
            name, foo, value = line.partition('!')
            if name is not None and len(name.strip()):
                cmd_output[name] = value

        return cmd_output

    def _execute_command_and_parse_concise(self, ssh_cmd):
        # This assume -nohdr is *not* present in ssh_cmd
        exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)

        output_lines = stdout.split('\n')
        header_line = output_lines[0]
        keylist = header_line.split('!')

        # For some reason, concise output gives one extra blank line at the end
        attrib_lines = output_lines[1:-1]
        cmd_output = {}
        lineindex = 0

        for attrib_line in attrib_lines:
            valuelist = attrib_line.split('!')
            attributes = {}
            valueindex = 0
            for key in keylist:
                attributes[key] = valuelist[valueindex]
                valueindex += 1

            cmd_output[lineindex] = attributes
            lineindex += 1

        return cmd_output

    def _get_system_info(self):
        ssh_cmd = 'lssystem -delim !'
        return self._execute_command_and_parse_detailed(ssh_cmd)

    def _get_pools(self):
        ssh_cmd = 'lsmdiskgrp -bytes -delim !'
        return self._execute_command_and_parse_concise(ssh_cmd)

    def _pool(self, p):
        return Pool(p['id'], p['name'], p['capacity'], p['free_capacity'],
                    self.sys_info.id)

    def _get_volumes(self):
        ssh_cmd = 'lsvdisk -bytes -delim !'
        return self._execute_command_and_parse_concise(ssh_cmd)

    def _get_volume(self, volume):
        ssh_cmd = 'lsvdisk -bytes -delim ! %s' % volume
        return self._execute_command_and_parse_detailed(ssh_cmd)

    def _volume(self, v):
        # v7k support 512 bytes/sec only, as the phy drive bs.
        # Its a bit complicated to reverse map v7k volume to
        # phy drive using the cli, so for now hardcode it as
        # thats the only supported bs at the drive level.
        bs = 512
<commit_msg>ibmv7k: Use int for representing total and free space<commit_after># Copyright (C) 2013 IBM Corporation
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
#
# Author: <NAME> (<EMAIL>)

import paramiko
from iplugin import IStorageAreaNetwork
from common import LsmError, ErrorNumber, uri_parse
from version import VERSION
from data import Volume, Initiator, FileSystem, Snapshot, \
    AccessGroup, System, Capabilities, Pool


def handle_ssh_errors(method):
    def ssh_wrapper(*args, **kwargs):
        try:
            return method(*args, **kwargs)
        except paramiko.SSHException as sshe:
            raise LsmError(ErrorNumber.TRANSPORT_COMMUNICATION, str(sshe))

    return ssh_wrapper


class V7kError(Exception):
    """
    Class represents a v7k cli bad return code
    """

    def __init__(self, errno, reason, *args, **kwargs):
        Exception.__init__(self, *args, **kwargs)
        self.errno = errno
        self.reason = reason


# NOTE: v7k cli doc doesn't list the possible error codes per cli.
# Thus do very generic and basic error handling for now.
# Just pass the error msg & code returned by the array back to lsm.
def handle_v7k_errors(method):
    def v7k_wrapper(*args, **kwargs):
        try:
            return method(*args, **kwargs)
        except V7kError as ve:
            msg = ve.reason + " (vendor error code= " + str(ve.errno) + ")"
            raise LsmError(ErrorNumber.PLUGIN_ERROR, msg)

    return v7k_wrapper


# A lite weight sshclient
class SSHClient():

    @handle_ssh_errors
    def __init__(self, hostname, login, passwd, conn_timeout=30):
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        try:
            self.ssh.connect(hostname, username=login, password=<PASSWORD>,
                             timeout=conn_timeout)
        except Exception as e:
            msg = ("Error while connecting via ssh to host %s : %s") % (hostname, e)
            raise paramiko.SSHException(msg)

    @handle_v7k_errors
    def execute(self, command, check_exit_code=True):
        stdin_strm, stdout_strm, stderr_strm = self.ssh.exec_command(command)

        stdin_strm.close()

        stdout_channel = stdout_strm.channel
        exit_code = stdout_channel.recv_exit_status()
        stdout_channel.close()

        stdout = stdout_strm.read()
        stdout_strm.close()

        stderr = stderr_strm.read()
        stderr_strm.close()

        if check_exit_code and exit_code != 0:
            errList = stderr.split(' ', 1)

            if exit_code == 127:
                # command not found error
                errno = exit_code
            else:
                # other errors
                errno = errList[0]

            reason = errList[1]

            raise V7kError(errno, reason)

        return (exit_code, stdout, stderr)

    @handle_ssh_errors
    def close(self):
        self.ssh.close()


# IBM V7000 storage lsm plugin

# *** lsm -- IBM V7000 terminology mapping ***
# volume -- v7k volume (aka vdisk)
# initiator -- host
# access group --  NA
# NA -- I/O group
# pool -- mdisk group
# volume-child dep -- ~fcmap and other maps if any
# job -- cli that can be invoked in async mode

class IbmV7k(IStorageAreaNetwork):

    def __init__(self):
        self.sys_info = None
        self.ssh = None

    def _execute_command_and_parse_detailed(self, ssh_cmd):
        exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)

        cmd_output = {}
        for line in stdout.split('\n'):
            name, foo, value = line.partition('!')
            if name is not None and len(name.strip()):
                cmd_output[name] = value

        return cmd_output

    def _execute_command_and_parse_concise(self, ssh_cmd):
        # This assume -nohdr is *not* present in ssh_cmd
        exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)

        output_lines = stdout.split('\n')
        header_line = output_lines[0]
        keylist = header_line.split('!')

        # For some reason, concise output gives one extra blank line at the end
        attrib_lines = output_lines[1:-1]
        cmd_output = {}
        lineindex = 0

        for attrib_line in attrib_lines:
            valuelist = attrib_line.split('!')
            attributes = {}
            valueindex = 0
            for key in keylist:
                attributes[key] = valuelist[valueindex]
                valueindex += 1

            cmd_output[lineindex] = attributes
            lineindex += 1

        return cmd_output

    def _get_system_info(self):
        ssh_cmd = 'lssystem -delim !'
        return self._execute_command_and_parse_detailed(ssh_cmd)

    def _get_pools(self):
        ssh_cmd = 'lsmdiskgrp -bytes -delim !'
        return self._execute_command_and_parse_concise(ssh_cmd)

    def _pool(self, p):
        return Pool(p['id'], p['name'], int(p['capacity']),
                    int(p['free_capacity']), self.sys_info.id)

    def _get_volumes(self):
        ssh_cmd = 'lsvdisk -bytes -delim !'
        return self._execute_command_and_parse_concise(ssh_cmd)

    def _get_volume(self, volume):
        ssh_cmd = 'lsvdisk -bytes -delim ! %s' % volume
        return self._execute_command_and_parse_detailed(ssh_cmd)

    def _volume(self, v):
        # v7k support 512 bytes/sec only, as the phy drive bs.
        # Its a bit complicated to reverse map v7k volume to
        # phy drive using the cli, so for now hardcode it as
        # thats the only supported bs at the drive level.
        bs = 512

{'fraction_non_alphanumeric': 0.08720647773279352, 'fraction_numerical': 0.00979757085020243, 'mean_word_length': 2.501842925999433, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '760647', 'n_tokens_mistral': 3841, 'n_tokens_neox': 3596, 'n_words': 1152}