def start(self, body): print body try: self.test_id = body['msg']['test_id'] except Exception as ex: print ex.message self.test_id = 54321 self.personal_cloud = body['msg']['test']['testClient'] self.stereotype_recipe = body['msg']['test']['testProfile'] try: self.personal_cloud_ip = body['msg']['{}-ip'.format(self.personal_cloud.lower())] self.personal_cloud_port = body['msg']['{}-port'.format(self.personal_cloud.lower())] except KeyError: pass # public cloud has none this args # set the capture flags # run the capture threads for proc in psutil.process_iter(): if proc.name() == self.proc_name: proc.kill() # force quit like a boss self.is_monitor_capturing = True # start personal cloud client self.sync_client = Thread(target=self._pc_client) self.sync_client.start() while self.is_sync_client_running is False: print "Launch wait ... {} ".format(self.personal_cloud) time.sleep(2) # start capturer loop self.traffic_monitor = Sniffer(personal_cloud=self.personal_cloud) self.traffic_monitor.run() # start emit metric to rabbit self.monitor = Thread(target=self._test) self.monitor.start() return "{} say start".format(self.whoami)
class Capture(object): def __init__(self, hostname): print "Constructor: " self.hostname = hostname self.sync_folder = None self.sync_folder_cleanup = None self.personal_cloud = None self.personal_cloud_ip = None self.personal_cloud_port = None self.test_id = None if os.name == "nt": self.platform_is_windows = True self.rmq_path = '/Users/vagrant/vagrant/rabbitmq' else: self.platform_is_windows = False self.rmq_path = "rabbitmq" self.rmq_path_url = None with open(self.rmq_path, 'r') as read_file: self.rmq_path_url = read_file.read().splitlines()[0] self.metric_network_counter_prev = None self.metric_prev = None self.traffic_monitor = None self.metric_network_counter_curr = None self.metric_network_netiface = None if self.platform_is_windows: # iface = "\\Device\\NPF_{EDB20D9F-1750-46D6-ADE7-76940B8DF917}" # iface = "\\Device\\NPF_{EDB20D9F-1750-46D6-ADE7-76940B8DF917}" iface_candidate = "Local Area Connection" # 10.0.2.15 self.metric_network_counter_curr = psutil.net_io_counters(pernic=True)[iface_candidate] self.metric_network_counter_prev = self.metric_network_counter_curr self.metric_network_netiface = iface_candidate # if iface == pcapy.findalldevs()[0]: # print "OKEY" # else: # iface = pcapy.findalldevs()[0] # print "WARNING!" # pass else: iface_candidate = ['enp4s0f2', 'eth0'] for iface in iface_candidate: if iface in psutil.net_io_counters(pernic=True): self.metric_network_counter_curr = psutil.net_io_counters(pernic=True)[iface] self.metric_network_counter_prev = self.metric_network_counter_curr self.metric_network_netiface = iface break else: continue # if none has been selected then, none network iface metric will be reported self.rmq_url = urlparse.urlparse(self.rmq_path_url) self.rmq_connection = None try: self.rmq_connection = pika.BlockingConnection( pika.ConnectionParameters( host=self.rmq_url.hostname, heartbeat_interval=0, # heartbeat forever virtual_host=self.rmq_url.path[1:], credentials=pika.PlainCredentials(self.rmq_url.username, self.rmq_url.password) ) ) except Exception as ex: print ex.message # exit(0) # failed to create rabbit connection self.rmq_channel = self.rmq_connection.channel() self.rmq_channel.exchange_declare(exchange='metrics', type='fanout') self.is_monitor_capturing = False # is_monitor_capturing self.is_sync_client_running = False # is_sync_client_running self.sync_client = None self.sync_client_proc = None self.sync_client_proc_pid = None self.stereotype_recipe = None self.monitor = None self.proc_name = None self.pc_cmd = None ''' Retrieve the psutil metrics ''' def notify_status(self): # retrieve the current state metrics from the personal client capturer # current metrics is a local variable metrics = {'cpu': 0, 'ram': 1, 'net': 2, 'bytes_sent': 1, 'bytes_recv': 1, 'packets_sent': 1, 'packets_recv': 1, 'errin': 0, 'errout': 0, 'dropin': 0, 'dropout': 0, 'disk': 0, 'files': 0, 'time': self.get_curr_milli_time() } try: if self.sync_client_proc is None and self.is_sync_client_running: # the sync client is running self.sync_client_proc = psutil.Process(self.sync_client_proc_pid) except Exception as ex: print ex.message # no sync client running return False # assign ram and cpu usage if self.sync_client_proc is not None: # we got a process and gota collect metrics try: cpu_usage = int(math.ceil(self.sync_client_proc.cpu_percent(0))) except Exception as ex: print ex.message return False ram_usage = self.sync_client_proc.memory_info().rss metrics['cpu'] = cpu_usage metrics['ram'] = ram_usage # assign the network usage if self.metric_prev is not None: last_time = self.metric_prev['metrics']['time'] self.metric_network_counter_curr = psutil.net_io_counters(pernic=True)[self.metric_network_netiface] curr_time = metrics['time'] elapsed_time = (curr_time - last_time) / 1000 # seconds if elapsed_time == 0: return True for key, value in self.metric_network_counter_curr.__dict__.items(): metrics[key] = (value - getattr(self.metric_network_counter_prev, key)) / elapsed_time # unit is seconds print " {} > pid[{}], running[{}], proc[{}], cpu[{}], ram[{}]".format(metrics['time'], self.sync_client_proc_pid, self.is_sync_client_running, self.sync_client_proc, metrics['cpu'], metrics['ram']) self.metric_network_counter_prev = self.metric_network_counter_curr # assign hard disk usage if self.platform_is_windows: drive_usage = self.get_sync_folder_size(start_path=self.sync_folder) metrics['disk'] = drive_usage else: drive_usage_cmd = ['/usr/bin/du', '-ks', '/home/vagrant/{}'.format(self.sync_folder)] drive_usage_output = subprocess.Popen(drive_usage_cmd, stdout=subprocess.PIPE) drive_usage = drive_usage_output.stdout.read() try: metrics['disk'] = int(drive_usage.split('\t')[0]) # kilo bytes cast string to int except Exception as ex: print "invalid literal for... memory unit" metrics['disk'] = 1 # assign file counter if self.platform_is_windows: num_files = self.count_sync_folder_files(start_path=self.sync_folder) metrics['files'] = num_files else: find_cmd = '/usr/bin/find /home/vagrant/{} -type f'.format(self.sync_folder).split() proc_find = subprocess.Popen(find_cmd, stdout=subprocess.PIPE) wc_cmd = '/usr/bin/wc -l'.split() proc_wc = subprocess.Popen(wc_cmd, stdin=proc_find.stdout, stdout=subprocess.PIPE) num_files = proc_wc.communicate()[0] try: metrics['files'] = int(num_files.split('\t')[0]) except Exception as ex: print ex.message print "invalid literal for... file counter" try: net_stats = self.traffic_monitor.notify_stats() # py_sniffer not unlocalizable metrics['data_rate_size_up'] = net_stats['data_rate']['size_up'] metrics['data_rate_size_down'] = net_stats['data_rate']['size_down'] metrics['data_rate_pack_up'] = net_stats['data_rate']['pack_up'] metrics['data_rate_pack_down'] = net_stats['data_rate']['pack_down'] metrics['meta_rate_size_up'] = net_stats['meta_rate']['size_up'] metrics['meta_rate_size_down'] = net_stats['meta_rate']['size_down'] metrics['meta_rate_pack_up'] = net_stats['meta_rate']['pack_up'] metrics['meta_rate_pack_down'] = net_stats['meta_rate']['pack_down'] except Exception as ex: print ex.message tags = '' if tags == '': tags = { 'profile': self.stereotype_recipe, 'credentials': 'NotUsed', 'client': self.whoami, 'test_id': self.test_id } data = { 'metrics': metrics, 'tags': tags } self.metric_prev = data # update the last emited metric msg = json.dumps(data) # print msg # this step sends the metric to the manager node self.rmq_channel.basic_publish( exchange='metrics', routing_key=self.hostname, body=msg) return True # asssign data and metadata from pysniffer # net_stats = self.traffic_monitor.notify_stats() def _test(self): self.is_monitor_capturing = True operations = 0 while self.is_monitor_capturing: # while the client is running operations += 1 if self.is_sync_client_running: self.is_sync_client_running = self.notify_status() # at each emit report if pid still running time.sleep(1) # get metrics each second else: self.sync_client_proc = None # this forwards the captured metric to the rabbit server time.sleep(5) # if client is not running wait 5 print "QUIT emit metrics" def _pc_client(self): print "start running [{}] {}".format(self.proc_name, self.pc_cmd) try_start = 10 while self.is_monitor_capturing: # keep resume personal cloud even if the personal cloud stops time.sleep(2) while self.is_sync_client_running is False and self.is_monitor_capturing: try_start -= 1 if try_start == 0: print "Unable to start {}".format(self.personal_cloud) break try: # pid lookup is_running = False client_pid = None candidate = [] personal_cloud_proc = None for proc in psutil.process_iter(): if proc.name() == self.proc_name: candidate.append(proc) personal_cloud_proc = proc is_running = True # google drive instances two process # pick the one with most ram if is_running: for p in candidate: if personal_cloud_proc.memory_info().rss >= p.memory_info().rss: pass else: personal_cloud_proc = p client_pid = personal_cloud_proc.pid self.is_sync_client_running = True self.sync_client_proc_pid = client_pid print "SYNC client running with pid[{}]".format(client_pid) else: self.sync_proc = subprocess.Popen(self.pc_cmd, shell=True) time.sleep(5) except Exception as ex: print ex.message print "Couldn't load sync client" @staticmethod def count_sync_folder_files(start_path = '.'): return sum([len(files) for r, d, files in os.walk(start_path)]) # count number of files in a dir # http://stackoverflow.com/questions/16910330/python-return-files-in-directory-and-subdirectory @staticmethod def get_sync_folder_size(start_path = '.'): total_size = 0 for dirpath, dirnames, filenames in os.walk(start_path): for f in filenames: try: fp = os.path.join(dirpath, f) total_size += os.path.getsize(fp) except Exception as ex: print ex.message # folder removed during getsize return total_size def start(self, body): print body try: self.test_id = body['msg']['test_id'] except Exception as ex: print ex.message self.test_id = 54321 self.personal_cloud = body['msg']['test']['testClient'] self.stereotype_recipe = body['msg']['test']['testProfile'] try: self.personal_cloud_ip = body['msg']['{}-ip'.format(self.personal_cloud.lower())] self.personal_cloud_port = body['msg']['{}-port'.format(self.personal_cloud.lower())] except KeyError: pass # public cloud has none this args # set the capture flags # run the capture threads for proc in psutil.process_iter(): if proc.name() == self.proc_name: proc.kill() # force quit like a boss self.is_monitor_capturing = True # start personal cloud client self.sync_client = Thread(target=self._pc_client) self.sync_client.start() while self.is_sync_client_running is False: print "Launch wait ... {} ".format(self.personal_cloud) time.sleep(2) # start capturer loop self.traffic_monitor = Sniffer(personal_cloud=self.personal_cloud) self.traffic_monitor.run() # start emit metric to rabbit self.monitor = Thread(target=self._test) self.monitor.start() return "{} say start".format(self.whoami) # self.sync_client = None # self.monitor = None def stop(self, body): print "try stop..." self.personal_cloud = body['msg']['test']['testClient'] self.remove_inner_path(path=self.sync_folder_cleanup) # self.sync_client = None # self.monitor = None # how to stop the process in windows ... todo lookup by psutil and clean up self.is_monitor_capturing = False # self.is_sync_client_running = False # self.monitor.join() # self.sync_client.join() # self.sync_client_proc_pid # how to stop process if self.platform_is_windows: # stop in windows for proc in psutil.process_iter(): if proc.name() == self.proc_name: proc.kill() # force quit like a boss else: # stop in linux pstring = self.proc_name for line in os.popen("ps ax | grep " + pstring + " | grep -v grep"): fields = line.split() proc_pid = fields[0] os.kill(int(proc_pid), signal.SIGKILL) self.traffic_monitor.rage_quit() return "{} say stop".format(self.whoami) @staticmethod def remove_inner_path(path): files = glob.glob(path) try: for f in files: if os.path.isdir(f): shutil.rmtree(f) elif os.path.isfile(f): os.remove(f) except Exception as ex: print ex.message @staticmethod def get_curr_milli_time(): return int(round(time.time() * 1000))