Пример #1
0
 def __init__(self, nodes):
     self.nodes = nodes
     self.node_manager = NodeManager()
     for node in self.nodes:
         self.node_manager.add_node(node)
         self.node_manager.update_node(node)
     self.node_manager.commit(time.time())
     self.steps = 0
Пример #2
0
 def execute(self, cmd, **kwargs):
     if 'log_true' in kwargs:
         if kwargs['log_true']:
             LOG.info('Node: %s Executing: %s' % (self.node.name, cmd))
         kwargs.pop('log_true')
     NodeManager.gen_ssh_config(self.node)
     if not isinstance(cmd, str):
         cmd = ' '.join(cmd)
     cmd_addition = ['ssh', '-i', SshUtil.get_id_rsa(), '-F',
                     SshUtil.get_config_file_path(),
                     self.node.name]
     if self.node.password:
         cmd_addition = ['sshpass', '-p', self.node.password] + cmd_addition
     if 'as_root' in kwargs:
         kwargs.pop('as_root')
         cmd = 'sudo ' + cmd
     cmd_addition.append(cmd)
     return execute(cmd_addition, **kwargs)
Пример #3
0
 def _copy(self, direction, local_path, remote_path, **kwargs):
     # TODO create dir is not existing
     NodeManager.gen_ssh_config(self.node)
     cmd = ['scp', '-i', SshUtil.get_id_rsa(), '-F',
            SshUtil.get_config_file_path()]
     if direction == 'to':
         if os.path.isdir(local_path):
             cmd.append('-r')
         cmd = cmd + [local_path,
                      ('%s:%s') % (self.node.name, remote_path)]
     if direction == 'from':
         if self.node.is_dir(remote_path):
             cmd.append('-r')
         cmd = cmd + [('%s:%s') % (self.node.name, remote_path),
                      local_path]
     if self.node.password:
         cmd = ['sshpass', '-p', self.node.password] + cmd
     return execute(cmd, **kwargs)
Пример #4
0
    def test_climb_degree(self):
        # intended path:
        # 0 -> 2 (largest) -> 9 (largest) -> 4 (smaller number than 7) -> 3 (smaller number than 4)-> 6 (larger), stop
        req = MockRequester({
            0: {1, 2},
            1: {0},
            2: {0, 1, 9},
            3: {0, 1, 2, 4, 6},
            4: {1, 2, 3, 7, 9},
            6: {1, 2, 3, 4, 5, 7, 8, 9},
            7: {1, 2, 3, 4, 9},
            9: {0, 1, 4, 7}
        })

        nm = NodeManager(req)

        output = _run(nm.climb_degree(0))

        self.assertEqual(6, output)
Пример #5
0
    def __init__(self, hostid):
        """
        Collects resource usage data of host
        and nodes.
        :param hostid: ROS_IP of this host
        :type hostid: string
        """
        super(HostStatisticsHandler, self).__init__(hostid)

        self.__update_interval = float(0)
        self.__publish_interval = 0
        self.__is_enabled = False
        self.__check_enabled = 0
        self.__search_nodes_inv = 0
        self.__init_params()
        self.__register_service()
        self.__lock = threading.Lock()
        self.__dict_lock = threading.Lock()

        self.pub = rospy.Publisher('/statistics_host',
                                   HostStatistics,
                                   queue_size=500)
        #: Used to store information about the host's status.
        self._status = HostStatus(rospy.Time.now())

        #: Interface to restart and stop nodes
        # or executing other commands.
        self.__node_manager = NodeManager()

        #: Dictionary holding all nodes currently running on the host.
        self.__node_list = {}

        # Base-stats for I/O
        self.__bandwidth_base = {}
        self.__msg_freq_base = {}
        self.__disk_write_base = {}
        self.__disk_read_base = {}

        self.__set_bases()
Пример #6
0
    def test_distance4(self):
        # intended expansion
        # dist 0: 0
        # dist 1: 1 2 3
        # dist 2: 4 5
        # dist 3: 6 7
        # dist 4: 8 9 10
        req = MockRequester({
            0: {1, 2, 3},
            1: set(),  # path that dies out
            2: {0, 1},  # paths that return
            3: {4, 5, 2},
            4: {5, 6},
            5: {0, 7},
            6: {6, 9},  # path loop
            7: {8, 10}
        })

        nm = NodeManager(req)

        output = _run(nm.distance4(0))

        self.assertEqual({8, 9, 10}, output)
Пример #7
0
    def test_complete_neighbourhood(self):
        req = MockRequester({
            0: {1, 2, 4, 5},
            1: {6},
            2: {5},
            3: {2, 4},
            4: {1},
            5: {1, 7},
            6: {7},
            7: {0, 6}
        })

        nm = NodeManager(req)

        _run(nm.complete_neighbourhood(0))

        self._assert_graph(
            {
                1: {2, 4, 5},
                2: {1, 4, 5},
                4: {1, 2, 5},
                5: {1, 2, 4}
            }, req)
Пример #8
0
    def test_concurrent_execution(self):
        req = MockRequester(
            {
                0: {1, 2, 3, 4, 5, 6, 7},
                1: set(),
                2: set(),
                3: set(),
                4: set(),
                5: set(),
                6: set(),
                7: set()
            },
            add_sleep=1)

        nm = NodeManager(req)

        try:
            # 7 * 6 / 2 = 21 connections to be added
            _run(asyncio.wait_for(nm.complete_neighbourhood(0), timeout=5))
        except asyncio.TimeoutError:
            self.fail("Timeout reached!")

        self._assert_graph({i: (set(range(1, 8)) - {i})
                            for i in range(1, 8)}, req)
Пример #9
0
    def __init__(self, hostid):
        """
        Collects resource usage data of host
        and nodes.
        :param hostid: ROS_IP of this host
        :type hostid: string
        """
        super(HostStatisticsHandler, self).__init__(hostid)

        self.__update_interval = float(0)
        self.__publish_interval = 0
        self.__is_enabled = False
        self.__check_enabled = 0
        self.__search_nodes_inv = 0
        self.__init_params()
        self.__register_service()
        self.__lock = threading.Lock()
        self.__dict_lock = threading.Lock()

        self.pub = rospy.Publisher('/statistics_host', HostStatistics, queue_size=500)
        #: Used to store information about the host's status.
        self._status = HostStatus(rospy.Time.now())

        #: Interface to restart and stop nodes
        # or executing other commands.
        self.__node_manager = NodeManager()

        #: Dictionary holding all nodes currently running on the host.
        self.__node_list = {}

        # Base-stats for I/O
        self.__bandwidth_base = {}
        self.__msg_freq_base = {}
        self.__disk_write_base = {}
        self.__disk_read_base = {}

        self.__set_bases()
Пример #10
0
#!/usr/bin/python
import os
import cgi, cgitb
from node_manager import NodeManager
from cgi_utils import send_response

form = cgi.FieldStorage()

node_id = form.getvalue('node_id')
node_name = form.getvalue('node_name')

nm = NodeManager()
nm.add_node(node_id, node_name)
send_response({}, 0)
Пример #11
0
#!/usr/bin/python
import os
import cgi, cgitb 
from node_manager import NodeManager
from cgi_utils import send_response

nm = NodeManager()
nodes = nm.list_node()
data = {'nodes': nodes}
send_response(data, 0)
Пример #12
0
class HostStatisticsHandler(StatisticsHandler):
    """
    Represents a host , limited to one instance per host.
    Collects statistics about the current state of the host and s
    ends them using the publisher-subscriber mechanism.
    """
    def __init__(self, hostid):
        """
        Collects resource usage data of host
        and nodes.
        :param hostid: ROS_IP of this host
        :type hostid: string
        """
        super(HostStatisticsHandler, self).__init__(hostid)

        self.__update_interval = float(0)
        self.__publish_interval = 0
        self.__is_enabled = False
        self.__check_enabled = 0
        self.__search_nodes_inv = 0
        self.__init_params()
        self.__register_service()
        self.__lock = threading.Lock()
        self.__dict_lock = threading.Lock()

        self.pub = rospy.Publisher('/statistics_host',
                                   HostStatistics,
                                   queue_size=500)
        #: Used to store information about the host's status.
        self._status = HostStatus(rospy.Time.now())

        #: Interface to restart and stop nodes
        # or executing other commands.
        self.__node_manager = NodeManager()

        #: Dictionary holding all nodes currently running on the host.
        self.__node_list = {}

        # Base-stats for I/O
        self.__bandwidth_base = {}
        self.__msg_freq_base = {}
        self.__disk_write_base = {}
        self.__disk_read_base = {}

        self.__set_bases()

    def __set_bases(self):
        """
        Calculate base stats for I/O at start of the node.
        Used to calculate difference to get per/s stats.
        """
        psutil.cpu_percent()
        psutil.cpu_percent(percpu=True)

        for interface in psutil.net_io_counters(True):

            netint = psutil.net_io_counters(True)[interface]
            total_bytes = netint.bytes_recv + netint.bytes_sent
            total_packages = netint.packets_sent + netint.packets_recv

            self.__bandwidth_base[interface] = total_bytes
            self.__msg_freq_base[interface] = total_packages

        dev_names = []
        for disk in psutil.disk_partitions():
            if all(['cdrom' not in disk.opts, 'sr' not in disk.device]):
                dev_names.append(disk.device)

        for key in psutil.disk_io_counters(True):
            if key in dev_names:
                disk = psutil.disk_io_counters(True)[key]
                self.__disk_read_base[key] = disk.read_bytes
                self.__disk_write_base[key] = disk.write_bytes

    def __register_service(self):
        """
        Register all services
        """
        ip = self._id.replace('.', '_')
        rospy.Service("/execute_node_reaction/%s" % ip, NodeReaction,
                      self.execute_reaction)

    def measure_status(self, event):
        """
        Collects information about the host's current status using psutils.
        Triggered periodically.
        """
        if not self.__is_enabled:
            pass
        if self.__is_enabled:
            self.__lock.acquire()
            # update node list
            self.__dict_lock.acquire()
            self.update_nodes()
            self.__dict_lock.release()
            # CPU
            self._status.add_cpu_usage(psutil.cpu_percent())
            self._status.add_cpu_usage_core(psutil.cpu_percent(percpu=True))
            # RAM
            self._status.add_ram_usage(psutil.virtual_memory().percent)
            # temp

            self.get_sensors()

            # Bandwidth and message frequency
            self.__measure_network_usage()
            # Disk usage
            self.__measure_disk_usage()
            self.__lock.release()

    def __measure_network_usage(self):
        """
        measure current network_io_counters
        """
        network_interfaces = psutil.net_io_counters(True)

        for key in network_interfaces:
            total_bytes = (network_interfaces[key].bytes_sent +
                           network_interfaces[key].bytes_recv
                           ) - self.__bandwidth_base[key]
            total_packages = (network_interfaces[key].packets_sent +
                              network_interfaces[key].packets_recv
                              ) - self.__msg_freq_base[key]

            bandwidth = total_bytes / self.__update_interval
            msg_frequency = total_packages / self.__update_interval
            self._status.add_bandwidth(key, bandwidth)
            self._status.add_msg_frequency(key, msg_frequency)

            # update base stats for next iteration
            self.__bandwidth_base[key] += total_bytes
            self.__msg_freq_base[key] += total_packages

    def __measure_disk_usage(self):
        """
        measure current disk usage
        """
        # Free Space on disks
        disks = psutil.disk_partitions()
        dev_name = []
        for disk in disks:
            if 'cdrom' not in disk.opts and 'sr' not in disk.device:
                free_space = psutil.disk_usage(disk.mountpoint).free / 2**20
                self._status.add_drive_space(disk.device, free_space)
                dev_name.append(disk.device)

        # Drive I/O
        drive_io = psutil.disk_io_counters(True)

        for disk in dev_name:
            if disk in drive_io:
                readb = drive_io[disk].read_bytes - self.__disk_read_base[disk]
                writeb = drive_io[disk].write_bytes - \
                    self.__disk_write_base[disk]

                read_rate = readb / self.__update_interval
                write_rate = writeb / self.__update_interval
                self._status.add_drive_read(disk, read_rate)
                self._status.add_drive_write(disk, write_rate)
                # update base stats for next iteration
                self.__disk_read_base[disk] += readb
                self.__disk_write_base[disk] += writeb
            else:
                # No information available - push None's
                self._status.add_drive_read(disk, None)
                self._status.add_drive_write(disk, None)

    def publish_status(self, event):
        """
        Publishes the current status to a topic using ROS's publisher-subscriber mechanism.
        Triggered periodically.
        """
        if not self.__is_enabled:
            pass
        if self.__is_enabled:
            self.__lock.acquire()
            self._status.time_end = rospy.Time.now()
            stats = self.__calc_statistics()
            self.__dict_lock.acquire()
            self.__publish_nodes()
            self.__dict_lock.release()
            self.pub.publish(stats)
            self._status.reset()
            self._status.time_start = rospy.Time.now()
            self.__lock.release()

    def __publish_nodes(self):
        """
        publishes current status of all nodes.
        """
        for node in self.__node_list:
            Thread(target=self.__node_list[node].publish_status).start()

    def __init_params(self):
        """
        Initializes params on the parameter server,
        """
        self.__publish_interval = rospy.get_param('~publish_interval', 10)
        self.__update_interval = self.__publish_interval / \
            float(rospy.get_param('~window_max_elements', 10))
        self.__is_enabled = rospy.get_param('/enable_statistics', False)
        self.__check_enabled = rospy.get_param('/arni/check_enabled_interval',
                                               10)
        self.__search_nodes_inv = rospy.get_param('~search_nodes', 5)

    def __calc_statistics(self):
        """
        Calculates statistics like mean, standard deviation and max from the status.
        Returns an instance of HostStatistics which can be published.

        :returns: HostStatistics
        """
        stats_dict = self._status.calc_stats()

        host_status = HostStatistics()

        host_status.host = self._id
        host_status.window_start = self._status.time_start
        host_status.window_stop = self._status.time_end

        for v in dir(host_status):
            if v in stats_dict:
                setattr(host_status, v, stats_dict[v])
        return host_status

    def execute_reaction(self, reaction):
        """
        Parses through the reaction and
        calls the appropriate method from the NodeManager. Uses ROS Services.
        Returns a message about operation's success.

        :param reaction: Reaction to be executed and node affected.
        :type reaction: NodeReaction.
        :returns: String
        """

        msg = ''
        if reaction.node not in self.__node_list:
            return 'Specified node is not running on this host.'

        if reaction.action == 'restart':
            node = self.__node_list[reaction.node]
            msg = self.__node_manager.restart_node(node)
            self.remove_node(reaction.node)
        elif reaction.action == 'stop':
            msg = self.__node_manager.stop_node(reaction.node)
            self.remove_node(reaction.node)
        elif reaction.action == 'command':
            msg = self.__node_manager.execute_command(reaction.command)
        else:
            msg = 'Failed to execute reaction, %s is no valid argument' % reaction.action
        rospy.loginfo('Executing reaction: %s' % msg)
        return msg

    def remove_node(self, node):
        """
        Removes the Node with the given id from the host.

        :param node_id: id of the node to be removed.
        :type node_id: String
        """
        if node in self.__node_list:
            del self.__node_list[node]

    def get_node_info(self, event):
        """
        Get the list of all Nodes running on the host.
        Update the __node_list
        """
        if not self.__is_enabled:
            pass

        if self.__is_enabled:
            nodes = []
            for node_name in rosnode.get_node_names():
                try:
                    node_api = rosnode.get_api_uri(rospy.get_master(),
                                                   node_name,
                                                   skip_cache=True)
                    if self._id in node_api[2]:
                        nodes.append(node_name)
                except:
                    pass

            for node in nodes:
                if node not in self.__node_list:
                    """TODO currently not catching the exception here - master not running is a hard error so it does
                    not make sense to continue running.."""
                    node_api = rosnode.get_api_uri(rospy.get_master(),
                                                   node,
                                                   skip_cache=True)

                    try:
                        pid = self.get_node_pid(node_api, node)
                        if not pid:
                            continue
                        node_process = psutil.Process(pid)
                        new_node = NodeStatisticsHandler(
                            self._id, node, node_process)
                        self.__dict_lock.acquire(True)
                        self.__node_list[node] = new_node
                        self.__dict_lock.release()
                    except psutil.NoSuchProcess:
                        rospy.loginfo('pid of node %s could not be fetched' %
                                      node)
                        continue

            self.__dict_lock.acquire()
            to_remove = []
            for node_name in self.__node_list:
                if node_name not in nodes:
                    rospy.logdebug('removing %s from host' % node_name)
                    to_remove.append(node_name)
            for node_name in to_remove:
                self.remove_node(node_name)
            self.__dict_lock.release()

    def get_node_pid(self, node_api, node):
        """
        Use the xmlrpclib Server Proxy to get
        node- pid
        :param node_api: API URI used for ServerProxy
        :type node_api: list
        :param node:  name of the node
        :type node: string
        """
        socket.setdefaulttimeout(1)
        try:
            code, msg, pid = xmlrpclib.ServerProxy(
                node_api[2]).getPid('/NODEINFO')

            return pid
        except socket.error:
            rospy.logdebug('Node %s is unreachable' % node)
            return False

    def update_nodes(self):
        """
        update the status of each node in its own threading
        """

        for node in self.__node_list:
            Thread(target=self.__node_list[node].measure_status).start()

    def get_sensors(self):
        """
        collects the current temperature of CPU
        and each core
        """

        sensors.init()
        added = []
        cpu_temp_c = []
        try:
            for chip in sensors.iter_detected_chips():
                for feature in chip:
                    if feature.name.startswith('temp'):
                        if ((feature.label.startswith('Physical')
                             or feature.label.startswith('CPU'))
                                and feature.label not in added):
                            self._status.add_cpu_temp(feature.get_value())
                        elif (feature.label.startswith('Core')
                              and feature.label not in added):
                            cpu_temp_c.append(feature.get_value())
                        added.append(feature.label)
        except sensors.SensorsError:
            pass
        if cpu_temp_c:
            try:
                self._status.add_cpu_temp_core(cpu_temp_c)
            except IndexError:
                pass
        sensors.cleanup()

    def check_enabled(self, event):
        """
        Periodically checks if /enable_statistics is ture
        if false no data will be collected / published
        """
        #rospy.logdebug('checking if enable_statistics is true')
        try:
            self.__is_enabled = rospy.get_param('/enable_statistics', False)
        except:
            pass
        #rospy.logdebug('enable_statistics is %s' % self.__is_enabled)

    @property
    def update_interval(self):
        return self.__update_interval

    @property
    def publish_interval(self):
        return self.__publish_interval

    @property
    def check_enabled_interval(self):
        return self.__check_enabled

    @property
    def search_nodes_inv(self):
        return self.__search_nodes_inv

    @property
    def status(self):
        return self._status
Пример #13
0
#!/usr/bin/python
import os
import cgi, cgitb
from node_manager import NodeManager
from cgi_utils import send_response

form = cgi.FieldStorage()

node_ids = form.getvalue('node_id_list').split(',')

nm = NodeManager()
for node_id in node_ids:
    nm.delete_node(node_id)
send_response({}, 0)
Пример #14
0
#!/usr/bin/python
import os
import cgi, cgitb
from node_manager import NodeManager
from cgi_utils import send_response

form = cgi.FieldStorage()

node_id = form.getvalue('node_id')
component = form.getvalue('component')
command = form.getvalue('command')

nm = NodeManager()
nm.control_node(node_id, component, command)
send_response({}, 0)
Пример #15
0
        node1 = Node(1, 0)
        node2 = Node(2, 0)
        manager.add_node(node1)
        manager.add_node(node2)
        while True:
            print("Fetching data from fog node...")
            header, node = serial_interface.receive_message(self.ser)
            # header = 'data'
            # node1.energy_level = random.randint(1, 50)
            # node2.energy_level = random.randint(1,50)
            print(f'Header: {header}')
            if header == DATA_HEADER:
                print(f'\t{node}')
                self.node_manager.update_node(node)
            elif header == ADD_NODE_HEADER:
                self.node_manager.add_node(node)
            elif header == REMOVE_NODE_HEADER:
                self.node_manager.remove_node(node.node_id)
            elif header == COMMIT_HEADER:
                self.node_manager.commit(time.time())
                print(f'\tSending orders...')
                serial_interface.send_action(self.ser, 1, Action.GATHER)
                serial_interface.send_action(self.ser, 2, Action.CHARGE)
            

manager = NodeManager()
listener = DataListener(manager)
plotter = Plotter(manager)
listener.start()
plt.show()
Пример #16
0
import threading
import time

from jobs import ScanJobManager
from node_manager import NodeManager

scm = ScanJobManager()
scm.NewJob(addr=("178.62.120.181", 80))

nm = NodeManager(scm)


def APIThread():
    nm.StartRegistrationListener()


def CreateJobThread():
    scm.GenerateJobs()


def SpreadJobThread():
    while True:
        nm.SpreadJobs(scm)
        time.sleep(10)


t_api = threading.Thread(target=APIThread)
t_api.start()

t_create_job = threading.Thread(target=CreateJobThread)
t_create_job.start()
Пример #17
0
from process_things import process_rawtx, process_rawblock
from node_manager import NodeManager
import os

from ptpdb import set_trace

controller = NodeManager(zmq_url=os.environ.get("ZMQ_URL"), )

controller.set_on_rawtx(process_rawtx)
controller.set_on_rawblock(process_rawblock)
controller.listen_to_subscriptions()

# For some logging magic
print("")
print("")
Пример #18
0
#!/usr/bin/python
import os
import cgi, cgitb 
from node_manager import NodeManager
from cgi_utils import send_response

form = cgi.FieldStorage() 

node_ids = form.getvalue('node_id_list').split(',')

nm = NodeManager()
for node_id in node_ids:
    nm.delete_node(node_id)
send_response({}, 0)
Пример #19
0
 def __init__(self, *args, **kwargs):
     super(UnitTesting, self).__init__(*args, **kwargs)
     self.node_manager = NodeManager()
Пример #20
0
from aiogram import Bot, Dispatcher, executor, types
from node_manager import NodeManager
from keyboards import new_keyboard, new_inline_keyboard
import configurer

bot = Bot(configurer.config['BOT']['token'])
dp = Dispatcher(bot)

node_client = NodeManager()


@dp.message_handler(commands=["start"])
async def start_message(message: types.Message):
    node_client.add_user(message.chat.id, message.from_user.username)
    node = node_client.get_start_node()
    keyboard = new_keyboard(node.buttons)
    await message.answer(node.text, reply_markup=keyboard)


@dp.message_handler(content_types=['text'])
async def send_text(message: types.Message):
    node = node_client.get_node_id(message)
    if node_client.check_inline_reply(node.node_id):
        keyboard = new_inline_keyboard(node.text)
        await message.answer("Переходи по ссылке:", reply_markup=keyboard)
    else:
        if node.text is not configurer.config['REPLY']['unfinished'] \
                and node.action is None:
            node_client.change_status(message)
        keyboard = new_keyboard(node.buttons)
        await message.answer(node.text, reply_markup=keyboard)
Пример #21
0
#!/usr/bin/python
import os
import cgi, cgitb 
from node_manager import NodeManager
from cgi_utils import send_response

form = cgi.FieldStorage() 

node_id = form.getvalue('node_id')
component = form.getvalue('component')
command = form.getvalue('command')

nm = NodeManager()
nm.control_node(node_id, component, command)
send_response({}, 0)
Пример #22
0
from node_manager import NodeManager, Node
import time

manager = NodeManager()

node1 = Node(1, 5)
node2 = Node(2, 5)

print("Add nodes")
manager.add_node(node1)
manager.add_node(node2)

print(manager.history)

node1.energy_level = 2

print("Update the energy value of a node")
manager.update_node(node1)
manager.commit(time.time())

print(manager.history)

print("Check if node 1 is in the system")
print(manager.node_is_in_system(node1.node_id))
print("Check if node with id 3 is in the system")
print(manager.node_is_in_system(3))


Пример #23
0
#!/usr/bin/python
import os
import cgi, cgitb
from node_manager import NodeManager
from cgi_utils import send_response

nm = NodeManager()
nodes = nm.list_node()
data = {'nodes': nodes}
send_response(data, 0)
Пример #24
0
class HostStatisticsHandler(StatisticsHandler):

    """
    Represents a host , limited to one instance per host.
    Collects statistics about the current state of the host and s
    ends them using the publisher-subscriber mechanism.
    """

    def __init__(self, hostid):
        """
        Collects resource usage data of host
        and nodes.
        :param hostid: ROS_IP of this host
        :type hostid: string
        """
        super(HostStatisticsHandler, self).__init__(hostid)

        self.__update_interval = float(0)
        self.__publish_interval = 0
        self.__is_enabled = False
        self.__check_enabled = 0
        self.__search_nodes_inv = 0
        self.__init_params()
        self.__register_service()
        self.__lock = threading.Lock()
        self.__dict_lock = threading.Lock()

        self.pub = rospy.Publisher('/statistics_host', HostStatistics, queue_size=500)
        #: Used to store information about the host's status.
        self._status = HostStatus(rospy.Time.now())

        #: Interface to restart and stop nodes
        # or executing other commands.
        self.__node_manager = NodeManager()

        #: Dictionary holding all nodes currently running on the host.
        self.__node_list = {}

        # Base-stats for I/O
        self.__bandwidth_base = {}
        self.__msg_freq_base = {}
        self.__disk_write_base = {}
        self.__disk_read_base = {}

        self.__set_bases()

    def __set_bases(self):
        """
        Calculate base stats for I/O at start of the node.
        Used to calculate difference to get per/s stats.
        """
        psutil.cpu_percent()
        psutil.cpu_percent(percpu=True)

        for interface in psutil.net_io_counters(True):

            netint = psutil.net_io_counters(True)[interface]
            total_bytes = netint.bytes_recv + netint.bytes_sent
            total_packages = netint.packets_sent + netint.packets_recv

            self.__bandwidth_base[interface] = total_bytes
            self.__msg_freq_base[interface] = total_packages

        dev_names = []
        for disk in psutil.disk_partitions():
            if all(['cdrom' not in disk.opts, 'sr' not in disk.device]):
                dev_names.append(disk.device)

        for key in psutil.disk_io_counters(True):
            if key in dev_names:
                disk = psutil.disk_io_counters(True)[key]
                self.__disk_read_base[key] = disk.read_bytes
                self.__disk_write_base[key] = disk.write_bytes

    def __register_service(self):
        """
        Register all services
        """
        ip = self._id.replace('.', '_')
        rospy.Service(
            "/execute_node_reaction/%s" % ip,
            NodeReaction, self.execute_reaction)

    def measure_status(self, event):
        """
        Collects information about the host's current status using psutils.
        Triggered periodically.
        """
        if not self.__is_enabled:
            pass
        if self.__is_enabled:
            self.__lock.acquire()
            # update node list
            self.__dict_lock.acquire()
            self.update_nodes()
            self.__dict_lock.release()
            # CPU
            self._status.add_cpu_usage(psutil.cpu_percent())
            self._status.add_cpu_usage_core(psutil.cpu_percent(percpu=True))
            # RAM
            self._status.add_ram_usage(psutil.virtual_memory().percent)
            # temp

            self.get_sensors()

            # Bandwidth and message frequency
            self.__measure_network_usage()
            # Disk usage
            self.__measure_disk_usage()
            self.__lock.release()

    def __measure_network_usage(self):
        """
        measure current network_io_counters
        """
        network_interfaces = psutil.net_io_counters(True)

        for key in network_interfaces:
            total_bytes = (network_interfaces[
                           key].bytes_sent + network_interfaces[key].bytes_recv) - self.__bandwidth_base[key]
            total_packages = (network_interfaces[
                              key].packets_sent + network_interfaces[key].packets_recv) - self.__msg_freq_base[key]

            bandwidth = total_bytes / self.__update_interval
            msg_frequency = total_packages / self.__update_interval
            self._status.add_bandwidth(key, bandwidth)
            self._status.add_msg_frequency(key, msg_frequency)

            # update base stats for next iteration
            self.__bandwidth_base[key] += total_bytes
            self.__msg_freq_base[key] += total_packages

    def __measure_disk_usage(self):
        """
        measure current disk usage
        """
        # Free Space on disks
        disks = psutil.disk_partitions()
        dev_name = []
        for disk in disks:
            if 'cdrom' not in disk.opts and 'sr' not in disk.device:
                free_space = psutil.disk_usage(disk.mountpoint).free / 2 ** 20
                self._status.add_drive_space(disk.device, free_space)
                dev_name.append(disk.device)

        # Drive I/O
        drive_io = psutil.disk_io_counters(True)

        for disk in dev_name:
            if disk in drive_io:
                readb = drive_io[disk].read_bytes - self.__disk_read_base[disk]
                writeb = drive_io[disk].write_bytes - \
                    self.__disk_write_base[disk]

                read_rate = readb / self.__update_interval
                write_rate = writeb / self.__update_interval
                self._status.add_drive_read(disk, read_rate)
                self._status.add_drive_write(disk, write_rate)
                # update base stats for next iteration
                self.__disk_read_base[disk] += readb
                self.__disk_write_base[disk] += writeb
            else:
                # No information available - push None's
                self._status.add_drive_read(disk, None)
                self._status.add_drive_write(disk, None)

    def publish_status(self, event):
        """
        Publishes the current status to a topic using ROS's publisher-subscriber mechanism.
        Triggered periodically.
        """
        if not self.__is_enabled:
            pass
        if self.__is_enabled:
            self.__lock.acquire()
            self._status.time_end = rospy.Time.now()
            stats = self.__calc_statistics()
            self.__dict_lock.acquire()
            self.__publish_nodes()
            self.__dict_lock.release()
            self.pub.publish(stats)
            self._status.reset()
            self._status.time_start = rospy.Time.now()
            self.__lock.release()

    def __publish_nodes(self):
        """
        publishes current status of all nodes.
        """
        for node in self.__node_list:
            Thread(target=self.__node_list[node].publish_status).start()

    def __init_params(self):
        """
        Initializes params on the parameter server,
        """
        self.__publish_interval = rospy.get_param('~publish_interval', 10)
        self.__update_interval = self.__publish_interval / \
            float(rospy.get_param('~window_max_elements', 10))
        self.__is_enabled = rospy.get_param('/enable_statistics', False)
        self.__check_enabled = rospy.get_param(
            '/arni/check_enabled_interval', 10)
        self.__search_nodes_inv = rospy.get_param('~search_nodes', 5)

    def __calc_statistics(self):
        """
        Calculates statistics like mean, standard deviation and max from the status.
        Returns an instance of HostStatistics which can be published.

        :returns: HostStatistics
        """
        stats_dict = self._status.calc_stats()

        host_status = HostStatistics()

        host_status.host = self._id
        host_status.window_start = self._status.time_start
        host_status.window_stop = self._status.time_end

        for v in dir(host_status):
            if v in stats_dict:
                setattr(host_status, v, stats_dict[v])
        return host_status

    def execute_reaction(self, reaction):
        """
        Parses through the reaction and
        calls the appropriate method from the NodeManager. Uses ROS Services.
        Returns a message about operation's success.

        :param reaction: Reaction to be executed and node affected.
        :type reaction: NodeReaction.
        :returns: String
        """

        msg = ''
        if reaction.node not in self.__node_list:
            return 'Specified node is not running on this host.'

        if reaction.action == 'restart':
            node = self.__node_list[reaction.node]
            msg = self.__node_manager.restart_node(node)
            self.remove_node(reaction.node)
        elif reaction.action == 'stop':
            msg = self.__node_manager.stop_node(reaction.node)
            self.remove_node(reaction.node)
        elif reaction.action == 'command':
            msg = self.__node_manager.execute_command(reaction.command)
        else:
            msg = 'Failed to execute reaction, %s is no valid argument' % reaction.action
        rospy.loginfo('Executing reaction: %s' % msg)
        return msg

    def remove_node(self, node):
        """
        Removes the Node with the given id from the host.

        :param node_id: id of the node to be removed.
        :type node_id: String
        """
        if node in self.__node_list:
            del self.__node_list[node]

    def get_node_info(self, event):
        """
        Get the list of all Nodes running on the host.
        Update the __node_list
        """
        if not self.__is_enabled:
            pass

        if self.__is_enabled:
            nodes = []
            for node_name in rosnode.get_node_names():
                try:
                    node_api = rosnode.get_api_uri(rospy.get_master(), node_name, skip_cache=True)
                    if self._id in node_api[2]:
                        nodes.append(node_name)
                except :
                    pass

            for node in nodes:
                if node not in self.__node_list:
                    """TODO currently not catching the exception here - master not running is a hard error so it does
                    not make sense to continue running.."""
                    node_api = rosnode.get_api_uri(rospy.get_master(), node, skip_cache=True)

                    try:
                        pid = self.get_node_pid(node_api, node)
                        if not pid:
                            continue
                        node_process = psutil.Process(pid)
                        new_node = NodeStatisticsHandler(
                            self._id, node, node_process)
                        self.__dict_lock.acquire(True)
                        self.__node_list[node] = new_node
                        self.__dict_lock.release()
                    except psutil.NoSuchProcess:
                        rospy.loginfo('pid of node %s could not be fetched' % node)
                        continue

            self.__dict_lock.acquire()
            to_remove = []
            for node_name in self.__node_list:
                if node_name not in nodes:
                    rospy.logdebug('removing %s from host' % node_name)
                    to_remove.append(node_name)
            for node_name in to_remove:
                self.remove_node(node_name)
            self.__dict_lock.release()

    def get_node_pid(self, node_api, node):
        """
        Use the xmlrpclib Server Proxy to get
        node- pid
        :param node_api: API URI used for ServerProxy
        :type node_api: list
        :param node:  name of the node
        :type node: string
        """
        socket.setdefaulttimeout(1)
        try:
            code, msg, pid = xmlrpclib.ServerProxy(
                node_api[2]).getPid('/NODEINFO')

            return pid
        except socket.error:
            rospy.logdebug('Node %s is unreachable' % node)
            return False

    def update_nodes(self):
        """
        update the status of each node in its own threading
        """

        for node in self.__node_list:
            Thread(target=self.__node_list[node].measure_status).start()

    def get_sensors(self):
        """
        collects the current temperature of CPU
        and each core
        """

        sensors.init()
        added = []
        cpu_temp_c = []
        try:
            for chip in sensors.iter_detected_chips():
                for feature in chip:
                    if feature.name.startswith('temp'):
                        if ((feature.label.startswith('Physical') or
                                feature.label.startswith('CPU')) and
                                feature.label not in added):
                            self._status.add_cpu_temp(feature.get_value())
                        elif (feature.label.startswith('Core')
                                and feature.label not in added):
                            cpu_temp_c.append(feature.get_value())
                        added.append(feature.label)
        except sensors.SensorsError:
            pass
        if cpu_temp_c:
            try:
                self._status.add_cpu_temp_core(cpu_temp_c)
            except IndexError:
                pass
        sensors.cleanup()

    def check_enabled(self, event):
        """
        Periodically checks if /enable_statistics is ture
        if false no data will be collected / published
        """
        #rospy.logdebug('checking if enable_statistics is true')
        try:
            self.__is_enabled = rospy.get_param('/enable_statistics', False)
        except:
            pass
        #rospy.logdebug('enable_statistics is %s' % self.__is_enabled)

    @property
    def update_interval(self):
        return self.__update_interval

    @property
    def publish_interval(self):
        return self.__publish_interval

    @property
    def check_enabled_interval(self):
        return self.__check_enabled

    @property
    def search_nodes_inv(self):
        return self.__search_nodes_inv

    @property 
    def status(self):
        return self._status
 def addNode(self, machineSpec):
     self.nodes.append(NodeManager(self, machineSpec))
Пример #26
0
#!/usr/bin/python
import os
import cgi, cgitb 
from node_manager import NodeManager
from cgi_utils import send_response

form = cgi.FieldStorage() 

node_id = form.getvalue('node_id')
node_name = form.getvalue('node_name')

nm = NodeManager()
nm.add_node(node_id, node_name)
send_response({}, 0)
Пример #27
0
class Simulation:
    def __init__(self, nodes):
        self.nodes = nodes
        self.node_manager = NodeManager()
        for node in self.nodes:
            self.node_manager.add_node(node)
            self.node_manager.update_node(node)
        self.node_manager.commit(time.time())
        self.steps = 0

    def step(self, action):
        self.steps += 1
        for index, node in enumerate(self.nodes):
            new_energy_value = node.update(action)
            if (new_energy_value is not None):
                self.node_manager.update_node(node)
        self.node_manager.commit(time.time())

        new_state = self.get_state()
        reward = self.calculate_reward(new_state, action)
        done = self.isDone()
        return new_state, reward, done

    def calculate_reward(self, energy_values, action):
        nulls = energy_values.isnull().sum(axis=1).iloc[0]
        # energy_too_low = self.get_state().mean(axis=1).iloc[0] < 1.8
        for value in energy_values:
            if energy_values[value].iloc[0] < 1.8:
                return -100

        if (nulls > 0):
            reward = -100
        elif (action is Action.CHARGE):
            reward = -1
        elif (action is Action.GATHER):
            reward = 1
        else:
            reward = 0
        return reward

    def get_state(self):
        return self.node_manager.get_most_recent_state().fillna(value=0)

    def isDone(self):
        energy_too_low = (self.get_state().mean(axis=1).iloc[0] < 1.8)
        return energy_too_low or (self.steps > 10000)


# nodes = []
# nodes.append(Node(1, 5))
# nodes.append(Node(2, 5))
# nodes.append(Node(3, 5))
# sim = Simulation(nodes)
# actions = [Action.CHARGE, Action.GATHER, Action.GATHER]
# new_state, reward, done = sim.step(actions)