File: //usr/local/qcloud/monitor/barad/comm/cutils.py
#common functions
import ConfigParser
import logging
import sys
import socket
import commands
import subprocess, threading, datetime, os, time, signal
import re
from urlparse import *
import constant
import urllib2
import cutils
CONFIG_PATH = '../etc/config.ini'
is_metal_g = -1
is_monios_g = -1
is_metal_mutex = threading.Lock()
is_monios_mutex = threading.Lock()
def get_agent_name(config_path):
config = ConfigParser.ConfigParser()
config.read(config_path)
return config.get('name','agent_name')
def get_agent_version(config_path):
config = ConfigParser.ConfigParser()
config.read(config_path)
return config.get('name','agent_version')
def generate_config(config_path, section_name):
config = ConfigParser.ConfigParser()
config.read(config_path)
config_dict = { }
if config.has_section(section_name):
for option_pair in config.items(section_name):
config_dict[option_pair[0]] = option_pair[1]
return config_dict
VM_METHON_DICT = {'/proc/cpuinfo':['hypervisor'],
'/sys/devices/system/clocksource/clocksource0/available_clocksource':['kvm'],
#in arm machine the value is cvm
'/sys/class/dmi/id/product_name':['CVM','KVM']}
def is_metal():
global is_metal_g
global is_metal_mutex
if is_metal_g != -1:
return is_metal_g
if is_metal_mutex.acquire():
if is_metal_g != -1:
is_metal_mutex.release()
return is_metal_g
for key in VM_METHON_DICT:
if os.path.exists(key):
with open(key) as fd:
temp = fd.read()
for key_word in VM_METHON_DICT[key]:
if(temp.find(key_word) != -1):
is_metal_g = 0
is_metal_mutex.release()
return is_metal_g
is_metal_g = 1
is_metal_mutex.release()
return is_metal_g
def is_minios():
global is_monios_g
global is_monios_mutex
if is_monios_g != -1:
return is_monios_g
if is_monios_mutex.acquire():
if is_monios_g != -1:
is_monios_mutex.release()
return is_monios_g
isminios = os.path.exists('/etc/minios_version')
is_monios_g = is_metal() & isminios
is_monios_mutex.release()
return is_monios_g
def console_logger():
logger = logging.getLogger()
logger.addHandler(logging.StreamHandler(sys.stdout))
logger.setLevel(logging.DEBUG)
return logger
def main_log(log_str):
""" barad main process log
:todo: logging rewrite.
"""
now = datetime.datetime.now()
timestamp = now.strftime('%Y-%m-%d %H:%M:%S')
log_line = "[%s] %s" % (timestamp, log_str)
with open("../log/main.log", "a+") as fd:
fd.write(log_line + "\n")
_local_ip = ''
def local_ip():
"""Get local ip """
global _local_ip
if len(_local_ip)>0:
return _local_ip
sock = ''
try:
url = get_url('NWSSender','new_nws_url','nws_url')
parse_url = urlparse(url)
domain = parse_url.netloc
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(1)
sock.connect((domain, 80))
_local_ip = sock.getsockname()[0]
except Exception as e:
main_log("get local ip fail, %s" % str(e))
_local_ip = ''
finally:
if sock:
sock.close()
return _local_ip
class CommUtils :
@staticmethod
def ExecuteCmd(cmd):
(status,output) = commands.getstatusoutput(cmd)
if status == 0:
return output
return ""
@staticmethod
def ExecuteTimeoutCommand(command, timeout):
"""call shell-command and either return its output or kill it
if it doesn't normally exit within timeout seconds and return None"""
start = datetime.datetime.now()
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
while process.poll() is None:
time.sleep(0.1)
now = datetime.datetime.now()
if (now - start).seconds> timeout:
#os.kill(process.pid, signal.SIGKILL)
#os.waitpid(-1, os.WNOHANG)
'''modified by cloudyang 2014.07.15
fix for the fd-leak bug in subprocess module in python 2.6
hope it works'''
process.kill()
process.wait()
return ""
return process.stdout.read()
@staticmethod
def GetBlockDevices():
try:
f = open('/proc/partitions','r')
l = f.readlines()
except Exception,e:
return
n = 0
res = []
for x in l:
n+=1
if n <= 2:
continue
arr = x.split()
chk_name = "/sys/class/block/" + arr[3]
if os.path.exists(os.path.realpath(chk_name)):
try_path = chk_name + "/dm/name"
try :
f2 = open(try_path)
best_name = "/dev/mapper/" + f2.read()[0:-1]
f2.close()
except :
best_name = "/dev/" + arr[3]
res.append(best_name)
f.close()
return res
@staticmethod
def dns_parse(url):
try:
parse_url = urlparse(url)
domain = parse_url.netloc
ip = socket.gethostbyname(domain)
pattern = "^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$"
if not re.match(pattern, ip):
return url
return url.replace(domain,ip)
except Exception, e:
return url
class incrementFileReadMng(object):
def __init__(self, max_read_size=4096*1024, get_last_fn=None):
self.max_read_size = max_read_size # max size to read each time
self.log_offset = -1
self.log_size = 0
self.fd = None
self.data_arrived = True
self.last = '' # last file, may be name or inode
self.current = ''
self.current_size = 0
self.get_last_fn = get_last_fn
def open_last_file(self, path):
log_size = os.path.getsize(path)
# no need to read rotated data
if log_size >= self.max_read_size:
raise Exception('pass')
# open path to avoid being rotated
self.current = open(path, 'r')
self.current_size = log_size
left = self.max_read_size - log_size
# get last file from self.last
last_file = self.get_last_fn(self.last)
last_size = os.path.getsize(last_file)
offset = last_size - left
if offset > self.log_offset:
self.log_offset = offset
self.fd = open(last_file, 'r')
self.log_size = last_size
# before open, path may be rotated, last was used to judge self.last for same file
def inc_open_file(self, path, last=None):
self.data_arrived = True
# rotated
if self.get_last_fn and self.last and last and last != self.last:
try:
self.open_last_file(path)
self.last = last
return True
except Exception:
self.inc_close_file()
self.last = last
try:
self.log_size = os.path.getsize(path)
# no data incremented
if self.log_offset == self.log_size:
self.data_arrived = False
return False
# first time run
if self.log_offset == -1:
self.log_offset = self.log_size
return False
# truncated or rotated
if self.log_offset > self.log_size:
self.log_offset = 0
# only read max_read_size data
if self.log_size - self.log_offset > self.max_read_size:
self.log_offset = self.log_size - self.max_read_size
self.fd = open(path, 'r')
except Exception:
self.inc_close_file()
return False
return True
# must close file after each read
def inc_close_file(self):
if self.current:
self.current.close()
self.current = None
if self.fd:
self.fd.close()
self.fd = None
self.log_size = 0
def open_current_file(self):
if self.fd:
self.fd.close()
self.log_offset = 0
self.fd = self.current
self.current = None
self.log_size = self.current_size
def inc_seek_read_lines(self, size):
if self.log_offset >= self.log_size:
if not self.current:
return ''
self.open_current_file()
self.fd.seek(self.log_offset, 0)
buf = self.fd.read(size)
if not buf and not self.current:
return buf
i = 1
d_len = len(buf)
if d_len < size and self.current:
left = size - d_len
self.open_current_file()
data = self.fd.read(left)
buf += data
d_len = len(buf)
# return data end with '\n' to avoid splitting data in lines
while i <= d_len:
if buf[-i] == '\n':
break
i += 1
res = buf[0:d_len - i + 1]
self.log_offset += d_len - i + 1
return res
# get last file if rotated
def get_offload_last(self, last):
return self.last
def check_net(url, time_out):
try:
urllib2.urlopen(url, timeout=time_out)
except:
return False
return True
def get_url(server,new_url,old_url):
get_config = generate_config(constant.PLUGIN_CONFIG_PATH,server)
new_url = get_config[new_url]
old_url = get_config[old_url]
if check_net(new_url,3) is True:
return new_url
else:
return old_url
if "__main__" == __name__:
while True:
print is_metal()
print is_minios()
print get_vm_uuid()
time.sleep(5)