示例#1
0
class TestCpuTimesCollector:
    def setup(self):
        self.host_os = Mock()
        self.host_os.cpu_count.return_value = 2
        self.host_os.cpu_times.return_value = CpuTimes(*[0 for _ in CPU_TIMES])

        self.shift = 5
        self.collector = CpuTimesCollector(self.shift, self.host_os)

    def test_returns_none_if_history_is_empty(self):
        cpu_count = self.host_os.cpu_count()
        for cpu_id in range(cpu_count):
            times = self.collector.get_times(cpu_id, self.shift)
            assert_equal(None, times)

    def test_returns_cpu_times_for_unfilled_history(self):
        self.collector._collect()

        cpu_count = self.host_os.cpu_count()
        for cpu_id in range(cpu_count):
            times = self.collector.get_times(cpu_id, self.shift)
            assert_is_instance(times, CpuTimes)

    def test_returns_cpu_times_for_filled_history(self):
        for i in range(self.shift + 1):
            self.collector._collect()

        cpu_count = self.host_os.cpu_count()
        for cpu_id in range(cpu_count):
            times = self.collector.get_times(cpu_id, self.shift)
            assert_is_instance(times, CpuTimes)
示例#2
0
class TestCpuTimesCollector:
    def setup(self):
        self.host_os = Mock()
        self.host_os.cpu_count.return_value = 2
        self.host_os.cpu_times.return_value = CpuTimes(*[0 for _ in CPU_TIMES])

        self.shift = 5
        self.collector = CpuTimesCollector(self.shift, self.host_os)

    def test_returns_none_if_history_is_empty(self):
        cpu_count = self.host_os.cpu_count()
        for cpu_id in range(cpu_count):
            times = self.collector.get_times(cpu_id, self.shift)
            assert_equal(None, times)

    def test_returns_cpu_times_for_unfilled_history(self):
        self.collector._collect()

        cpu_count = self.host_os.cpu_count()
        for cpu_id in range(cpu_count):
            times = self.collector.get_times(cpu_id, self.shift)
            assert_is_instance(times, CpuTimes)

    def test_returns_cpu_times_for_filled_history(self):
        for i in range(self.shift + 1):
            self.collector._collect()

        cpu_count = self.host_os.cpu_count()
        for cpu_id in range(cpu_count):
            times = self.collector.get_times(cpu_id, self.shift)
            assert_is_instance(times, CpuTimes)
示例#3
0
文件: linux.py 项目: blin/zabby
class Linux(HostOS):
    AVAILABLE_MEMORY_TYPES = set([
        'total',
        'free',
        'buffers',
        'cached',
        'available',
        'pavailable',
        'used',
        'pused',
    ])
    AVAILABLE_DISK_DEVICE_STATS_TYPES = set(['sectors', 'operations'])

    def __init__(self):
        super(Linux, self).__init__()

        self._disk_device_stats_collector = DiskDeviceStatsCollector(900, self)
        self._collectors.append(self._disk_device_stats_collector)

        self._cpu_times_collector = CpuTimesCollector(900, self)
        self._collectors.append(self._cpu_times_collector)

    def fs_size(self, filesystem):
        """
        Uses statvfs system call to obtain information about filesystem

        See `man 3 statvfs` for more information
        """
        statvfs_struct = os.statvfs(filesystem)
        total = statvfs_struct.f_blocks * statvfs_struct.f_bsize
        free = statvfs_struct.f_bavail * statvfs_struct.f_bsize
        return free, total

    def fs_inodes(self, filesystem):
        """
        Uses statvfs system call to obtain information about filesystem

        See `man 3 statvfs` for more information
        """
        statvfs_struct = os.statvfs(filesystem)
        total = statvfs_struct.f_files
        free = statvfs_struct.f_ffree
        return free, total

    def net_interface_names(self):
        """
        Uses /proc/net/dev to obtain device names

        See `man 5 proc` for more information
        """
        interface_infos = self._net_interface_infos()

        return set(interface_infos.keys())

    def net_interface_info(self, net_interface_name):
        """
        Uses /proc/net/dev to obtain device names

        See `man 5 proc` for more information
        """
        interface_infos = self._net_interface_infos()

        return interface_infos[net_interface_name]

    def _net_interface_infos(self):
        lines = lines_from_file("/proc/net/dev")
        interface_info_lines = lines[2:]

        interface_stats = dict()
        for interface_info_line in interface_info_lines:
            interface_name, interface_info = interface_info_line.split(':')
            interface_name = interface_name.strip()
            interface_info = interface_info.split()

            incoming = [int(value) for value in interface_info[0:4]]
            outgoing = [int(value) for value in interface_info[8:12]]
            collisions = [int(interface_info[14])]
            interface_stats[interface_name] = NetworkInterfaceInfo(
                *(incoming + outgoing + collisions))
        return interface_stats

    def process_infos(self):
        """
        Uses /proc/{pid}/status to obtain information about process name,
        effective UID, state and used memory
        Uses /proc/{pid}/cmdline to obtain information about command line

        {pid} directories are obtained once by listing all files containing only
        digits in /proc

        See `man 5 proc` for more information
        """
        for process_id in self._process_ids():
            try:
                try:
                    command_line = self._process_command_line(process_id)
                except OperatingSystemError:
                    # kernel threads do not contain command line
                    # we are not interested in them
                    continue

                status = self._process_status(process_id)
                yield ProcessInfo(name=status['Name'],
                                  uid=status['Uid'],
                                  state=status['State'],
                                  command_line=command_line,
                                  used_memory=status['VmSize'])
            except IOError:
                # process with process_id no longer exists
                continue

    def _process_ids(self):
        return [
            dir_name for dir_name in os.listdir('/proc') if dir_name.isdigit()
        ]

    def _process_command_line(self, process_id):
        proc_cmd_line = os.path.join('/proc', process_id, 'cmdline')
        proc_cmd_line = lines_from_file(proc_cmd_line)[0]

        return proc_cmd_line.replace('\0', ' ').rstrip()

    def _process_status(self, process_id):
        process_status_file_path = os.path.join('/proc', process_id, 'status')
        process_status = dict_from_file(process_status_file_path, ':\t')

        process_status['Uid'] = int(process_status['Uid'].split('\t')
                                    [0])  # only effective UID is needed
        process_status['State'] = PROCESS_STATE_MAP.get(
            process_status['State'], 'sleep')

        # VmSize field can be missing
        # See ${linux}/fs/proc/array.c:proc_pid_status for more information
        if 'VmSize' in process_status:
            process_status['VmSize'] = to_bytes(
                *process_status['VmSize'].split())
        else:
            process_status['VmSize'] = 0

        return process_status

    def uid(self, username):
        """
        Uses getpwnam system call to obtain UID

        See `man 3 getpwnam` for more information
        """
        return self._passwd(username).uid

    def _passwd(self, username):
        pointer_to_passwd = _libc.getpwnam(b(username))
        if pointer_to_passwd:
            return pointer_to_passwd[0]
        else:
            raise OperatingSystemError('Invalid name: {0}'.format(username))

    def memory(self):
        """
        Uses /proc/meminfo to obtain information on memory usage

        See `man 5 proc` for more information
        """
        mem_info = dict_from_file('/proc/meminfo')
        total = to_bytes(*mem_info['MemTotal:'].split())
        free = to_bytes(*mem_info['MemFree:'].split())
        buffers = to_bytes(*mem_info['Buffers:'].split())
        cached = to_bytes(*mem_info['Cached:'].split())

        available = free + buffers + cached
        pavailable = (available * 100) / total

        used = total - available
        pused = (used * 100) / total

        return {
            'total': total,
            'free': free,
            'buffers': buffers,
            'cached': cached,
            'available': available,
            'pavailable': pavailable,
            'used': used,
            'pused': pused,
        }

    def disk_device_names(self):
        """
        Obtains information from '/proc/diskstats'

        See `man 5 proc` for more information
        """
        return set(self._disk_devices_stats().keys())

    def disk_device_stats(self, device):
        """
        Obtains information from '/proc/diskstats'

        See `man 5 proc` for more information
        """
        return self._disk_devices_stats()[device]

    def _disk_devices_stats(self):
        diskstats = dict()
        disks = lists_from_file('/proc/diskstats')
        for disk in disks:
            device = disk[2]
            diskstat = DiskDeviceStats(read_sectors=int(disk[5]),
                                       read_operations=int(disk[3]),
                                       read_bytes=0,
                                       write_sectors=int(disk[9]),
                                       write_operations=int(disk[7]),
                                       write_bytes=0)
            diskstats[device] = diskstat
        return diskstats

    def disk_device_stats_shifted(self, device, shift, now):
        """
        Obtains information from DiskDeviceStatsCollector
        """
        return self._disk_device_stats_collector.get_stats(device, shift, now)

    def cpu_count(self):
        """
        Obtains information from /proc/stat

        See `man 5 proc` for more information
        """
        return len(self._cpus_times())

    def cpu_times(self, cpu_id):
        """
        Obtains information from /proc/stat

        See `man 5 proc` for more information
        """
        return self._cpus_times()[cpu_id]

    def _cpus_times(self):
        stats = lists_from_file('/proc/stat')
        cpus_times = []
        for stat in stats:
            key, values = stat[0], stat[1:]
            if key.startswith('cpu') and key != 'cpu':
                cpu_times = [int(cpu_time) for cpu_time in values[:7]]
                cpus_times.append(CpuTimes(*cpu_times))

        return cpus_times

    def cpu_times_shifted(self, cpu_id, shift):
        """
        Obtains information from CpuTimesCollector
        """
        return self._cpu_times_collector.get_times(cpu_id, shift)

    def hostname(self, hostname_type):
        """
        Obtains information from python socket.gethostname()

        :param hostname_type: is ignored
        """
        return socket.gethostname()

    def uname(self):
        """
        Obtains information from python os.uname()
        """
        return os.uname()

    def uptime(self):
        """
        Obtains information from /proc/uptime

        See `man 5 proc` for more information
        """
        return int(float(lists_from_file('/proc/uptime')[0][0]))

    def max_number_of_running_processes(self):
        """
        Obtains information from /proc/sys/kernel/pid_max

        See `man 5 proc` for more information
        """
        return int(lines_from_file("/proc/sys/kernel/pid_max")[0])

    def system_load(self):
        """
        Obtains information from python os.getloadavg()
        """
        return SystemLoad(*os.getloadavg())

    def swap_size(self, device):
        """
        Obtains information from sysinfo system call

        See `man 2 sysinfo` for more information

        :param device: ignored, always returns system wide information
        """
        sysinfo_struct = StructSysinfo()
        _libc.sysinfo(byref(sysinfo_struct))

        return (sysinfo_struct.freeswap * sysinfo_struct.mem_unit,
                sysinfo_struct.totalswap * sysinfo_struct.mem_unit)

    def swap_info(self):
        """
        Obtains information from /proc/vmstat

        See `man 5 proc` for more information
        """
        vmstat = dict_from_file('/proc/vmstat')

        return SwapInfo(read=int(vmstat['pswpin']),
                        write=int(vmstat['pswpout']))

    def swap_device_names(self):
        """
        Obtains information from /proc/swaps

        See `man 5 proc` for more information
        """
        swaps = lists_from_file('/proc/swaps')

        devices = set()
        for swap in swaps[1:]:  # skip header
            swap_type = swap[1]
            if swap_type != 'partition':
                continue

            device_path = swap[0]
            device = device_path.split('/')[-1]
            devices.add(device)

        return devices
示例#4
0
文件: linux.py 项目: blin/zabby
class Linux(HostOS):
    AVAILABLE_MEMORY_TYPES = set([
        'total',
        'free',
        'buffers',
        'cached',
        'available',
        'pavailable',
        'used',
        'pused',
    ])
    AVAILABLE_DISK_DEVICE_STATS_TYPES = set(['sectors', 'operations'])

    def __init__(self):
        super(Linux, self).__init__()

        self._disk_device_stats_collector = DiskDeviceStatsCollector(900, self)
        self._collectors.append(self._disk_device_stats_collector)

        self._cpu_times_collector = CpuTimesCollector(900, self)
        self._collectors.append(self._cpu_times_collector)

    def fs_size(self, filesystem):
        """
        Uses statvfs system call to obtain information about filesystem

        See `man 3 statvfs` for more information
        """
        statvfs_struct = os.statvfs(filesystem)
        total = statvfs_struct.f_blocks * statvfs_struct.f_bsize
        free = statvfs_struct.f_bavail * statvfs_struct.f_bsize
        return free, total

    def fs_inodes(self, filesystem):
        """
        Uses statvfs system call to obtain information about filesystem

        See `man 3 statvfs` for more information
        """
        statvfs_struct = os.statvfs(filesystem)
        total = statvfs_struct.f_files
        free = statvfs_struct.f_ffree
        return free, total

    def net_interface_names(self):
        """
        Uses /proc/net/dev to obtain device names

        See `man 5 proc` for more information
        """
        interface_infos = self._net_interface_infos()

        return set(interface_infos.keys())

    def net_interface_info(self, net_interface_name):
        """
        Uses /proc/net/dev to obtain device names

        See `man 5 proc` for more information
        """
        interface_infos = self._net_interface_infos()

        return interface_infos[net_interface_name]

    def _net_interface_infos(self):
        lines = lines_from_file("/proc/net/dev")
        interface_info_lines = lines[2:]

        interface_stats = dict()
        for interface_info_line in interface_info_lines:
            interface_name, interface_info = interface_info_line.split(':')
            interface_name = interface_name.strip()
            interface_info = interface_info.split()

            incoming = [int(value) for value in interface_info[0:4]]
            outgoing = [int(value) for value in interface_info[8:12]]
            collisions = [int(interface_info[14])]
            interface_stats[interface_name] = NetworkInterfaceInfo(
                *(incoming + outgoing + collisions))
        return interface_stats

    def process_infos(self):
        """
        Uses /proc/{pid}/status to obtain information about process name,
        effective UID, state and used memory
        Uses /proc/{pid}/cmdline to obtain information about command line

        {pid} directories are obtained once by listing all files containing only
        digits in /proc

        See `man 5 proc` for more information
        """
        for process_id in self._process_ids():
            try:
                try:
                    command_line = self._process_command_line(process_id)
                except OperatingSystemError:
                    # kernel threads do not contain command line
                    # we are not interested in them
                    continue

                status = self._process_status(process_id)
                yield ProcessInfo(
                    name=status['Name'],
                    uid=status['Uid'],
                    state=status['State'],
                    command_line=command_line,
                    used_memory=status['VmSize']
                )
            except IOError:
                # process with process_id no longer exists
                continue

    def _process_ids(self):
        return [dir_name
                for dir_name in os.listdir('/proc')
                if dir_name.isdigit()]

    def _process_command_line(self, process_id):
        proc_cmd_line = os.path.join('/proc', process_id, 'cmdline')
        proc_cmd_line = lines_from_file(proc_cmd_line)[0]

        return proc_cmd_line.replace('\0', ' ').rstrip()

    def _process_status(self, process_id):
        process_status_file_path = os.path.join('/proc', process_id, 'status')
        process_status = dict_from_file(process_status_file_path, ':\t')

        process_status['Uid'] = int(
            process_status['Uid'].split('\t')[0]
        )  # only effective UID is needed
        process_status['State'] = PROCESS_STATE_MAP.get(
            process_status['State'], 'sleep'
        )

        # VmSize field can be missing
        # See ${linux}/fs/proc/array.c:proc_pid_status for more information
        if 'VmSize' in process_status:
            process_status['VmSize'] = to_bytes(
                *process_status['VmSize'].split())
        else:
            process_status['VmSize'] = 0

        return process_status

    def uid(self, username):
        """
        Uses getpwnam system call to obtain UID

        See `man 3 getpwnam` for more information
        """
        return self._passwd(username).uid

    def _passwd(self, username):
        pointer_to_passwd = _libc.getpwnam(b(username))
        if pointer_to_passwd:
            return pointer_to_passwd[0]
        else:
            raise OperatingSystemError('Invalid name: {0}'.format(username))

    def memory(self):
        """
        Uses /proc/meminfo to obtain information on memory usage

        See `man 5 proc` for more information
        """
        mem_info = dict_from_file('/proc/meminfo')
        total = to_bytes(*mem_info['MemTotal:'].split())
        free = to_bytes(*mem_info['MemFree:'].split())
        buffers = to_bytes(*mem_info['Buffers:'].split())
        cached = to_bytes(*mem_info['Cached:'].split())

        available = free + buffers + cached
        pavailable = (available * 100) / total

        used = total - available
        pused = (used * 100) / total

        return {
            'total': total,
            'free': free,
            'buffers': buffers,
            'cached': cached,
            'available': available,
            'pavailable': pavailable,
            'used': used,
            'pused': pused,
        }

    def disk_device_names(self):
        """
        Obtains information from '/proc/diskstats'

        See `man 5 proc` for more information
        """
        return set(self._disk_devices_stats().keys())

    def disk_device_stats(self, device):
        """
        Obtains information from '/proc/diskstats'

        See `man 5 proc` for more information
        """
        return self._disk_devices_stats()[device]

    def _disk_devices_stats(self):
        diskstats = dict()
        disks = lists_from_file('/proc/diskstats')
        for disk in disks:
            device = disk[2]
            diskstat = DiskDeviceStats(
                read_sectors=int(disk[5]),
                read_operations=int(disk[3]),
                read_bytes=0,
                write_sectors=int(disk[9]),
                write_operations=int(disk[7]),
                write_bytes=0
            )
            diskstats[device] = diskstat
        return diskstats

    def disk_device_stats_shifted(self, device, shift, now):
        """
        Obtains information from DiskDeviceStatsCollector
        """
        return self._disk_device_stats_collector.get_stats(device, shift, now)

    def cpu_count(self):
        """
        Obtains information from /proc/stat

        See `man 5 proc` for more information
        """
        return len(self._cpus_times())

    def cpu_times(self, cpu_id):
        """
        Obtains information from /proc/stat

        See `man 5 proc` for more information
        """
        return self._cpus_times()[cpu_id]

    def _cpus_times(self):
        stats = lists_from_file('/proc/stat')
        cpus_times = []
        for stat in stats:
            key, values = stat[0], stat[1:]
            if key.startswith('cpu') and key != 'cpu':
                cpu_times = [int(cpu_time) for cpu_time in values[:7]]
                cpus_times.append(CpuTimes(*cpu_times))

        return cpus_times

    def cpu_times_shifted(self, cpu_id, shift):
        """
        Obtains information from CpuTimesCollector
        """
        return self._cpu_times_collector.get_times(cpu_id, shift)

    def hostname(self, hostname_type):
        """
        Obtains information from python socket.gethostname()

        :param hostname_type: is ignored
        """
        return socket.gethostname()

    def uname(self):
        """
        Obtains information from python os.uname()
        """
        return os.uname()

    def uptime(self):
        """
        Obtains information from /proc/uptime

        See `man 5 proc` for more information
        """
        return int(float(lists_from_file('/proc/uptime')[0][0]))

    def max_number_of_running_processes(self):
        """
        Obtains information from /proc/sys/kernel/pid_max

        See `man 5 proc` for more information
        """
        return int(lines_from_file("/proc/sys/kernel/pid_max")[0])

    def system_load(self):
        """
        Obtains information from python os.getloadavg()
        """
        return SystemLoad(*os.getloadavg())

    def swap_size(self, device):
        """
        Obtains information from sysinfo system call

        See `man 2 sysinfo` for more information

        :param device: ignored, always returns system wide information
        """
        sysinfo_struct = StructSysinfo()
        _libc.sysinfo(byref(sysinfo_struct))

        return (sysinfo_struct.freeswap * sysinfo_struct.mem_unit,
                sysinfo_struct.totalswap * sysinfo_struct.mem_unit)

    def swap_info(self):
        """
        Obtains information from /proc/vmstat

        See `man 5 proc` for more information
        """
        vmstat = dict_from_file('/proc/vmstat')

        return SwapInfo(read=int(vmstat['pswpin']),
                        write=int(vmstat['pswpout']))

    def swap_device_names(self):
        """
        Obtains information from /proc/swaps

        See `man 5 proc` for more information
        """
        swaps = lists_from_file('/proc/swaps')

        devices = set()
        for swap in swaps[1:]:  # skip header
            swap_type = swap[1]
            if swap_type != 'partition':
                continue

            device_path = swap[0]
            device = device_path.split('/')[-1]
            devices.add(device)

        return devices