ok

Mini Shell

Direktori : /opt/cloudlinux/venv/lib/python3.11/site-packages/lvestats/lib/info/
Upload File :
Current File : //opt/cloudlinux/venv/lib/python3.11/site-packages/lvestats/lib/info/lveinfomain.py

# coding=utf-8
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT

from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import csv
import logging
import os
import sys

from sqlalchemy.exc import OperationalError, ProgrammingError

import lvestats
import lvestats.lib.commons.decorators
from lvestats.lib import uidconverter
from lvestats.lib.commons import dateutil
from lvestats.lib.commons.func import get_ascii_table
from lvestats.lib.commons.logsetup import setup_logging
from lvestats.lib.config import ConfigError
from lvestats.lib.config import read_config, is_normalized_user_cpu
from lvestats.lib.dbengine import make_db_engine, MakeDbException
from lvestats.lib.jsonhandler import prepare_data_json
from lvestats.lib.lveinfolib import OutputFormatter, HistoryShowUnion, \
    servers_info, get_supported_columns
from lvestats.lib.lveinfolib_gov import HistoryShowDBGov
from lvestats.lib.parsers.lveinfoargparse import lveinfo_parser, dbgov_parser, DEF_BLANK_VALUE

log = setup_logging({}, caller_name='lveinfo', file_level=logging.ERROR, console_level=logging.ERROR)

NAME = 'lveinfo'


def _convert_to_dict(rows, fields):
    """
    Convert rows and its headers name to list dictionaries
    :param list|tuple|generator rows:
    :param list|tuple fields:
    :return list:
    """
    return [dict(zip(fields, row_)) for row_ in rows]


def save_csv(rows, fields, stream):
    """
    Save rows and its headers to stream
    :param list|tuple|generator rows:
    :param list|tuple fields: first csv file line
    :param file stream: stream to write data
    :return:
    """
    csv_writer = csv.writer(stream)
    csv_writer.writerow(fields)
    csv_writer.writerows(rows)


def is_cpu_output_normalizable(namespace):
    """
    Normalization is done only if namespace.style == 'user', user id is specified, and either
    csv or json output selected

    :param namespace: command line options/settings
    :return: True if normalizagin of CPU should be done
    """
    return namespace.style == "user" and (namespace.csv or namespace.json) and namespace.id


def normalize_cpu(rows, fields):
    """
    Normalize CPU data, making limit always be 100%. This is used to show end user usage relative to their limits
    :param list rows: rows with data
    :param list|tuple fields: columns name
    :return list: normalized rows
    """
    if 'lCPU' in fields:
        lcpu_index = fields.index('lCPU')
    else:
        return rows

    if 'aCPU' in fields:
        acpuindex = fields.index('aCPU')
    else:
        acpuindex = -1

    if 'mCPU' in fields:
        mcpuindex = fields.index('mCPU')
    else:
        mcpuindex = -1

    new_rows = []
    for _prow in rows:
        _row = list(_prow)
        new_rows.append(_row)
        lcpu = float(_row[lcpu_index])
        _row[lcpu_index] = 100.
        if acpuindex != -1:
            _row[acpuindex] = float(_row[acpuindex]) / lcpu * 100
        if mcpuindex != -1:
            _row[mcpuindex] = float(_row[mcpuindex]) / lcpu * 100
    return new_rows


def main_(config, dbengine=None, argv_=None):
    if dbengine is None:
        try:
            dbengine = make_db_engine(cfg=config)
        except MakeDbException as e:
            log.error(str(e))
            return

    if argv_ is None:
        _args = sys.argv[1:]
    else:
        _args = list(argv_)

    if '--dbgov' in _args:
        namespace, output_formatted, rows = dbgov_main(config, _args, dbengine)
    else:
        parser = lveinfo_parser(name=NAME, ver=lvestats.__version__, config=config, dbengine=dbengine)
        namespace = parser.parse_args(_args)  # parsing command line

        if namespace.servers_info:
            output_formatted = OutputFormatter(('Server', 'LVE version'))
            rows = servers_info(dbengine)
        else:
            output_formatted, rows = lvestats_main(dbengine, namespace, parser)

    output_formatted.set_rows(rows)

    # return values in bytes for json and csv
    # otherwise, return bytes
    if namespace.csv or namespace.json:
        output_formatted.add_order(fields=['aIO', 'mIO', 'lIO'], order=lambda x_: round(x_ / 1024., 3))  # pylint: disable=round-builtin

    if namespace.csv:
        save_csv(output_formatted, output_formatted.get_fields(), stream=namespace.csv)
    elif namespace.json:
        return prepare_data_json(_convert_to_dict(output_formatted, output_formatted.fields))
    else:
        # make ascii-table output human readable
        output_formatted.add_order(fields=['aVMem', 'mVMem', 'lVMem', 'aPMem', 'mPMem', 'lPMem', 'aIO', 'mIO', 'lIO'],
                                   order='bytes')
        output_formatted.add_order(
            fields=['aEP', 'mEP', 'lEP', 'EPf', 'VMemF', 'CPUf', 'aNproc', 'mNproc', 'lNproc',
                    'PMemF', 'NprocF', 'IOf', 'aIOPS', 'mIOPS', 'lIOPS', 'IOPSf'], order='powers_of_1000')
        output_formatted.add_order(['uCPU', 'uEP', 'uVMem', 'uPMem', 'uIO', 'uNproc', 'uIOPS'], 'percentage')

        return get_ascii_table(output_formatted, fields=output_formatted.fields)


def lvestats_main(dbengine, namespace, parser):
    output_formatted = OutputFormatter(
        namespace.show_columns,
        # convert From To %m-%d %H:%M (for example "12-29 09:46")
        orders=[(['From', 'To'], 'datetime'), (['From', 'To'], 'strftime')])
    output_formatted.add_order(fields=['aCPU', 'mCPU', 'lCPU', 'aIO', 'mIO', 'lIO'],
                               order=lambda x_: int(round(x_)))  # pylint: disable=round-builtin
    utc_from = dateutil.local_to_gm(getattr(namespace, 'from'))
    utc_to = dateutil.local_to_gm(namespace.to)
    if os.environ.get('LVEINFODEBUG'):
        log_ = setup_logging({}, caller_name='lveinfo', console_level=logging.DEBUG)
    else:
        log_ = None
    history_show = HistoryShowUnion(
        dbengine=dbengine,
        period_from=utc_from,
        period_to=utc_to,
        uid=namespace.id,
        show_columns=output_formatted.get_fields(),
        server_id=namespace.server_id,
        time_unit=namespace.time_unit,
        limit=namespace.limit,
        by_usage=namespace.by_usage,
        by_usage_percentage=namespace.percentage / 100.,
        by_fault=namespace.by_fault,
        threshold=namespace.threshold,
        order_by=namespace.order_by,
        log=log_ or log)
    history_show.set_normalised_output()

    if namespace.time_unit == -1:  # using dynamic time-unit
        rows = history_show.proceed_dyn_time_unit()
    else:
        rows = history_show.proceed()
    if ((namespace.user or namespace.reseller_name)
            and namespace.display_username):
        output_formatted.add_order(
            ['ID'], lambda x: namespace.user or namespace.reseller_name)
    elif namespace.display_username:
        # try convert user id to user name
        output_formatted.add_order(
            ['ID'], lambda x: uidconverter.uid_to_username(
                x, parser.get_default('server_id'),
                namespace.server_id, dbengine) or x)

    # replace unsupported columns item to blank-value
    supported_columns_ = get_supported_columns(lve_version=parser.lve_version)
    all_columns = get_supported_columns()
    unsupported_columns = set(all_columns).difference(set(supported_columns_))
    if unsupported_columns:
        output_formatted.add_order(
            fields=unsupported_columns,
            order=lambda _: DEF_BLANK_VALUE if namespace.blank_value is None else namespace.blank_value)
    if is_normalized_user_cpu() and is_cpu_output_normalizable(namespace):
        rows = normalize_cpu(rows, history_show.show_columns)
    return output_formatted, rows


def dbgov_main(config, _args, dbengine):
    _args.remove('--dbgov')
    parser = dbgov_parser(config=config, dbengine=dbengine)
    namespace = parser.parse_args(_args)  # parsing command line
    output_formatted = OutputFormatter(
        fields=namespace.format,
        orders=[
            (['FROM', 'TO'], 'datetime'),
            (['FROM', 'TO'], lambda dt: OutputFormatter.strftime(
                dt, '%m-%d %H:%M')),
            (['TS'], 'datetime'),
            (['TS'], lambda dt: OutputFormatter.strftime(
                dt, '%m-%d %H:%M:%S')),
            (['CPU'], lambda x: 0 if x < 0.001 else x),
            (['READ', 'WRITE'], lambda x: 0 if x < 0.001 else x),
        ]
    )
    utc_from = dateutil.local_to_gm(getattr(namespace, 'from'))
    utc_to = dateutil.local_to_gm(namespace.to)

    history_show = HistoryShowDBGov(
        dbengine=dbengine, period_from=utc_from, period_to=utc_to,
        uid=namespace.id, show_columns=output_formatted.get_fields(),
        server_id=namespace.server_id, order_by=namespace.order_by,
        limit=namespace.limit, cfg=config, time_unit=namespace.time_unit,
        by_usage=namespace.by_usage, by_usage_percentage=namespace.percentage / 100.
    )
    if namespace.time_unit == -1:
        rows = history_show.history_dbgov_show_dynamic()
    else:
        rows = history_show.history_dbgov_show()
    return namespace, output_formatted, rows


@lvestats.lib.commons.decorators.no_sigpipe
def main(config, *args, **kwargs):
    try:
        str_ = main_(config, *args, **kwargs)
    except (OperationalError, ProgrammingError) as ex:
        log.error(str(ex))
    else:
        if str_:
            print(str_)


if __name__ == '__main__':
    try:
        main(read_config())
    except ConfigError as ce:
        ce.log_and_exit()

Zerion Mini Shell 1.0