File: //usr/local/qcloud/monitor/barad/plugin/collector/utils/host_proxy.py
#!/usr/bin/env python
# 0. head
import sys, os
import socket
import time
import select
import threading
import SocketServer
import zipfile
import re
sys.path.append(os.getcwd()+"/../lib/")
#import psutil
# 1. macro define and global variable
# BUFFER_SIZE = 256
LOG_PATH = '../log/host_proxy.log'
VER_FILE = '/var/run/Tx-proxy.lock'
conf_file = '../etc/host_proxy.conf'
proxy_name = 'Tx-proxy'
os_name = 'Unknown OS'
os_list = 'Tencent tlinux CentOS Linux SLES Ubuntu'
MAX_LOG_SIZE = 1024 * 1024 * 1024
def quote_str(cmd):
badchars = "\n&;|'\"$()`>"
for char in badchars:
cmd = cmd.replace(char, "_")
return cmd
# write log to logfile
def write_log(str, timestamp = True):
with open(LOG_PATH,'a+') as f:
if timestamp:
f.write("[%s] %s" % (time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())), str) )
else:
f.write(str)
# write version to /var/run/Tx-proxy.lock
def write_version():
if not os.path.exists(conf_file):
write_log("host_proxy.conf does not exist!\n")
sys.exit(1)
with open(conf_file, 'r') as f1:
ver = f1.read().strip()
write_log("Set process version to %s..." % ver)
with open(VER_FILE,'w') as f2:
f2.write(ver)
write_log("Done\n", False)
def change_proc_name(new_name=proxy_name):
write_log("Set process name to %s..." % new_name)
try:
import setproctitle
setproctitle.setproctitle(new_name)
# checking whether set process name succ or not
if not setproctitle.getproctitle().startswith(new_name):
write_log("set process name to %s failed \n" % new_name)
sys.exit(1)
except Exception, e:
import traceback
write_log(traceback.format_exc())
sys.exit(1)
write_log("Done\n", False)
# daemon
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
write_log("Daemonize...")
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
write_log("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) )
sys.exit(1)
#os.chdir("/")
os.umask(0)
os.setsid()
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
write_log("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) )
sys.exit(1)
for f in sys.stdout, sys.stderr: f.flush()
si = open(stdin, 'r')
so = open(stdout, 'a+')
se = open(stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
write_log("Done\n", False)
def get_proc_num(proc_name):
proc_name = quote_str(proc_name)
cmd = 'ps aux | grep -w ' + proc_name + ' | grep -v grep | wc -l';
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
sys.exit(1)
#for p in psutil.process_iter():
# try:
# if p.name() == proc_name:
# proc_num += 1
# except Exception, e:
# pass
proc_num=int(out[0].strip())
return proc_num
# a. check whether the port is occupied, exit if true
def check_proc(procname = proxy_name):
write_log("Check whether the port is occupied...")
cnt = get_proc_num(procname)
if cnt > 1:
# host_agent has been running
write_log('%s has been running, so exit\n' %(procname) )
sys.exit(1)
write_log("Done\n", False)
return True
# log rotate
def log_rotate():
try:
fsize = os.path.getsize(LOG_PATH)
except OSError,e:
write_log('get host_proxy size failed.')
return False
if fsize > MAX_LOG_SIZE:
try:
status = os.system('cd ../log/;rm -f host_proxy.log.tar.gz;tar -czvf host_proxy.log.tar.gz host_proxy.log;cd ../bin')
except OSError,e:
write_log('compress host_proxy.log failed.')
return False
try:
with open(LOG_PATH, "w"):
pass
except OSError,e:
write_log('open host_proxy.log failed.')
return False
write_log('logrotate success')
return True
# check os
def check_os():
write_log('Check os name...')
global os_name
with open('/etc/os-release','r') as f:
for l in f:
key = l.split("=")[0]
if "NAME" in key:
os_name = (l.split("=")[1]).split('"')[1]
break
if os_name not in os_list:
write_log('Error: Unknown OS\n')
sys.exit(1)
write_log('Done, os_name:%s\n' %(os_name), False)
# check whether iscsid is running
def check_iscsid(procname):
cnt = get_proc_num(procname)
if cnt < 1:
# open-iscsi is not running
return False
return True
# b. check whether iscsi is OK, and if not, start it
def check_iscsi(procname = 'iscsid'):
write_log("Check whether iscsid is running...")
global os_name
if not check_iscsid(procname):
if os_name == 'Tencent tlinux' or os_name == 'CentOS Linux':
cmd = 'systemctl stop iscsid.socket && sleep 1 && systemctl start iscsid.socket'
write_log('os is %s, and %s is not running, try to handle: %s\n' %(os_name, procname, cmd) )
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
sys.exit(1)
cmd = 'systemctl start iscsi && systemctl start iscsid'
write_log('%s is not running, try to handle: %s\n' %(procname, cmd) )
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
sys.exit(1)
if not check_iscsid(procname):
# open-iscsi is still not running
write_log('Failed to start iscsi by handling: %s, so exit\n' %(cmd) )
sys.exit(1)
write_log("Done\n", False)
return True
def check_iscsi_config():
write_log("Check the iscsi config in /etc/iscsi/iscsid.conf...")
iscsi_conf='/etc/iscsi/iscsid.conf'
restart = False
if os.path.exists(iscsi_conf):
with open(iscsi_conf, 'r') as f:
lines = f.readlines()
with open(iscsi_conf, 'w') as f_w:
for line in lines:
if 'node.startup' in line and '#' not in line:
if "manual" in line:
restart = True
line = line.replace("manual", "automatic")
f_w.write(line)
else:
write_log("iscsi config file does not exist!")
sys.exit(1)
if restart:
cmd = quote_str('systemctl restart iscsid')
write_log('iscsi config file is changed, try to restart by: %s...' %(cmd) )
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
sys.exit(1)
write_log("Done\n", False)
#c. check the ethernet, exit if 'Broadcom Limited Device d802' not in it or the eth driver is not bnxt_en
def check_Ethernet(vendor = "14e4", device_id = "d802", driver = "bnxt_en"):
write_log("Check whether the ethernet is 'Broadcom' with vendor 14e4 and device id d802...")
vendor=quote_str(vendor)
device_id=quote_str(device_id)
cmd = 'lspci -nn -vv | grep Ethernet | grep Broadcom | grep \'' + vendor + ':' + device_id + '\''
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
return False
if len(out) < 1:
write_log('Ethernet is not Broadcom with vendor 14e4 and device id d802, so exit\n')
sys.exit(1)
write_log("Done\n", False)
write_log("Check whether the eth driver is 'bnxt_en'...")
cmd = 'ethtool -i eth1 | grep -w ' + driver
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
return False
if len(out) < 1:
write_log('Ethernet driver is not %s, so exit\n' %(driver) )
sys.exit(1)
write_log("Done\n", False)
return True
# check whether eth1 is up now
def is_eth_up(ethernet = "eth1", ip = "169.254.68.1"):
ethernet = quote_str(ethernet)
cmd = 'ifconfig -a | grep -w ' + ethernet
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error: %s, exit\n" % e)
sys.exit(1)
if len(out) < 1:
write_log('Error\n%s is not exist, so exit\n' %(ethernet))
sys.exit(1)
for line in out:
if 'UP' not in line:
return False
if 'RUNNING' not in line:
return False
ip = quote_str(ip)
cmd = 'ifconfig -a | grep -A 5 -w ' + ethernet + ' | grep -w ' + ip
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error: %s, exit\n" % e)
sys.exit(1)
if len(out) >= 1:
return True
return False
def check_eth_status():
global os_name
if os_name == 'Ubuntu':
check_eth_status_ubuntu()
else:
check_eth_status_centos()
def check_eth_status_ubuntu(ethernet = "eth1", ip = "169.254.68.1", netmask = "255.255.255.252"):
write_log("Check whether the eth1 is set to up permanently...\n")
global os_name
need_format = True
ifcfg_file = "/etc/network/interfaces"
tmp = ip.split('.')
base = ''
for i in range(len(tmp)-1):
base += tmp[i] + '.'
network = base + '0'
bc = str(255 - int(netmask.split('.')[-1]))
broadcast = base + bc
cmd = 'grep eth1 /etc/network/interfaces'
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error: %s, exit\n" % e)
sys.exit(1)
if out == '':
need_format = False
else:
need_format = True
if need_format == True:
with open(ifcfg_file, 'w') as f:
conf = "auto " + ethernet
conf += "\niface " + ethernet + " inet static"
conf += "\naddress " + ip
conf += "\nnetwork " + network
conf += "\nnetmask " + netmask
conf += "\nbroadcast " + broadcast
# conf += "\ngateway " + gateway
f.write(conf)
if not is_eth_up(ethernet, ip):
ethernet = quote_str(ethernet)
cmd = 'ifdown ' + ethernet + ' && ifup ' + ethernet
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error: %s, exit\n" % e)
sys.exit(1)
if not is_eth_up(ethernet, ip):
write_log('Error:%s is down, and try to up it failed\n' %(ethernet))
sys.exit(1)
write_log("Done\n", False)
return True
#c. up eth1 with ip "169.254.68.1/30" if it is down
def check_eth_status_centos(ethernet = "eth1", ip = "169.254.68.1", netmask = "255.255.255.252"):
write_log("Check whether the eth1 is set to up permanently...")
global os_name
ifcfg_path = "/etc/sysconfig/network-scripts"
if os_name == 'SLES':
ifcfg_path = "/etc/sysconfig/network"
tmp = ip.split('.')
base = ''
for i in range(len(tmp)-1):
base += tmp[i] + '.'
network = base + '0'
bc = str(255 - int(netmask.split('.')[-1]))
broadcast = base + bc
ethernet = quote_str(ethernet)
if os.path.exists(ifcfg_path):
conf_file_name = 'ifcfg-' + ethernet
eth_ifcfg_path = os.path.join(ifcfg_path,conf_file_name)
with open(eth_ifcfg_path,'w') as f:
conf = "NAME=" + ethernet
conf += "\nDEVICE=" + ethernet
conf += "\nBOOTPROTO=static"
conf += "\nTYPE=Ethernet"
conf += "\nBROADCAST=" + broadcast
conf += "\nIPADDR=" + ip
conf += "\nIPV6INIT=yes"
conf += "\nIPV6_AUTOCONF=yes"
conf += "\nNETMASK=" + netmask
conf += "\nNETWORK=" + network
conf += "\nONBOOT=yes\n"
if os_name == 'SLES':
conf += "STARTMODE=auto\n"
f.write(conf)
if not is_eth_up(ethernet, ip):
cmd = 'ifdown ' + ethernet + ' && ifup ' + ethernet
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error: %s, exit\n" % e)
sys.exit(1)
if not is_eth_up(ethernet, ip):
write_log('Error:%s is down, and try to up it failed\n' %(ethernet))
sys.exit(1)
write_log("Done\n", False)
return True
else:
write_log('Warning: open ifcfg file failed, can not persist the ethernet config!\n')
if not is_eth_up(ethernet, ip):
write_log('Now try to up %s just for once.\n' %(ethernet))
ethernet = quote_str(ethernet)
ip = quote_str(ip)
netmask = quote_str(netmask)
broadcast = quote_str(broadcast)
cmd = 'ifconfig ' + ethernet + ' down && ifconfig ' + ethernet + ' ' + ip + 'netmask ' + netmask + ' broadcast ' + broadcast + ' up'
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error: %s, exit\n" % e)
sys.exit(1)
if not is_eth_up(ethernet, ip):
write_log('Error:%s is down, and try to up it failed\n' %(ethernet))
sys.exit(1)
return False
# get diskid from /sys/block/sd*/device/model
def get_diskid(device):
diskid_info_path = os.path.join('/sys/block/', device,'device/model')
# legal char in the file(/sys/block//device/model) except number and letter
diskid_legal_char = '-_.!?'
#write_log('try to get disk-info from path: %s\n' %(diskid_info_path) )
try:
f = open(diskid_info_path,'r').read()
except IOError, e:
write_log("can't open diskid_info_path:%s, with error %s\n" % (diskid_info_path,e))
return (2,e)
if len(f) < 1:
write_log("No info about the diskid of %s\n" % x)
return (3,'')
#remove the illegal char in device/model
disk_id = ''.join(list(filter(lambda ch: ch.isalnum() or ch in diskid_legal_char,f)))
if('disk-' not in disk_id):
#write_log("the format of %s is illegal\n" % disk_id)
return (1,disk_id)
return (0,disk_id)
# set the timeout in /sys/block/sd*/device/timeout
def set_timeout(device,timeout=8640):
timeout_path = os.path.join('/sys/block/',os.path.basename(device),'device/timeout')
try:
f = open(timeout_path,'w+')
except IOError, e:
write_log("set timeout error: %s\n" % e)
return 1
try:
original=f.read().strip()
except IOError, e:
original=''
write_log("read timeout error: %s\n" % e)
write_log("Original timeout of %s is %s \n" % (device, original))
if original != '8640':
write_log("Now Change timeout from %s to %d \n" % (original, timeout))
try:
f.write("%d"%timeout)
except IOError, e:
write_log("write timeout error: %s\n" % e)
else:
write_log("No need to change timeout!\n")
f.close()
# set the max_sectors_kb in /sys/block/sd*/queue/max_sectors_kb
def set_max_sectors_kb(device,max_sectors_kb=512):
dest_path = os.path.join('/sys/block/',os.path.basename(device),'queue/max_sectors_kb')
try:
f = open(dest_path,'w+')
except IOError, e:
write_log("set max_sectors_kb error: %s\n" % e)
return 1
try:
original=f.read().strip()
except IOError, e:
original=''
write_log("read max_sectors_kb error: %s\n" % e)
write_log("Original max_sectors_kb of %s is %s \n" % (device, original))
if original == '' or int(original) > 512:
write_log("Now Change max_sectors_kb from %s to %d \n" % (original, max_sectors_kb))
try:
f.write("%d"%max_sectors_kb)
except IOError, e:
write_log("write max_sectors_kb error: %s\n" % e)
else:
write_log("No need to change max_sectors_kb!\n")
f.close()
def set_softlink(sl_path,real_path):
if os.path.exists(sl_path):
#now check the softlink
if os.path.islink(sl_path) and os.readlink(sl_path) == real_path:
return 0
else:
write_log("The softlink %s incorrect,try to remove it\n" % (sl_path))
if not os.path.isdir(sl_path):
try:
os.remove(sl_path)
except OSError,e:
write_log("Remove %s failed, with error: %s\n" % (sl_path,e))
return 1
else:
try:
os.rmdir(sl_path)
except OSError,e:
write_log("Remove directory %s failed, with error: %s\n" % (sl_path,e))
return 1
write_log("Now set softlink from %s to %s\n" % (sl_path, real_path))
os.symlink(real_path, sl_path)
# set timeout for new session
set_timeout(os.path.basename(real_path))
set_max_sectors_kb(os.path.basename(real_path))
return 0
# d. if the iscsi has login but there's no softlink, try to creat softlink for them
def check_softlink():
sd_info_path = '/sys/block/'
real_path_prefix = '/dev/'
device_keyword = 'sd'
for x in os.listdir(sd_info_path):
#write_log('test device: %s\n' % x)
if device_keyword in x:
#write_log('check the device type and diskid for %s\n' %(x) )
# There should be a correspond device in /dev
real_path = os.path.join(real_path_prefix, x)
if not os.path.exists(real_path):
write_log('device %s is not exist in /dev!\n' %(x) )
continue
(status,disk_id) = get_diskid(x)
if status > 0:
continue
sl_path = os.path.join('/dev/disk/by-id/',disk_id)
set_softlink(sl_path,real_path)
sl_path = os.path.join('/dev/disk/by-id/','virtio-' + disk_id)
set_softlink(sl_path,real_path)
# check softlink every 5 mins
def do_check_softlink():
while(True):
check_softlink()
time.sleep(5)
# run do_check_softlink by thread
def creat_softlink_checker():
write_log("Creat a thread for softlink_checker...")
t = threading.Thread(target=do_check_softlink, name='SoftlinkCheckerThread')
t.start()
write_log("Done\n", False)
# check whether the session has been established
def check_session(target = ''):
cmd = "iscsiadm -m session"
no_session = "iscsiadm: No active sessions."
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
return 1
if len(out) < 1:
write_log("Check Session: no Result\n")
return 2
for line in out:
write_log("Session : %s\n" % line)
if target in line:
if no_session in line:
write_log("Check Session: No active sessions\n")
return 3
else:
return 0
write_log("Check Session: Do not find session %s\n" %(target))
return 4
# just for login and logout
def exec_cmd(cmd = ''):
write_log('%s, handle cmd: %s\n' %(time.ctime(), cmd) )
cmd = quote_str(cmd)
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
return (1, 'Exec Cmd Error')
if len(out) < 1:
write_log('%s Error :No results\n' %(cmd) )
return (2, 'No Results Error')
res = False
for line in out:
write_log('%s' %(line) )
if 'successful' in line:
res = True
write_log('Exec successful\n')
break
if not res:
write_log('%s Error: Exec Failed\n' %(cmd) )
return (3, 'Exec Failed')
return (0, 'OK')
# after a target is logined, there will be a disk id in /dev/disk/by-path/
def find_diskid(target = ''):
# check disk by-path
id_path = '/dev/disk/by-path/'
for x in os.listdir(id_path):
write_log('pase: %s\n' % x)
if target in x:
write_log('target: %s, disk by-path: %s\n' %(target, x) )
uuid_path = os.path.join(id_path, x)
if not os.path.islink(uuid_path):
write_log('uuid_path %s is not link\n' %(uuid_path) )
#return (1, 'INVALID UUID PATH')
continue
real_path = os.readlink(uuid_path)
if real_path[-1] in '0123456789' and 'part' in x:
write_log('real_path: %s is a partition,check next\n' %(real_path) )
continue
write_log('real_path: %s\n' %(real_path) )
path = os.path.abspath(os.path.join(id_path, real_path))
write_log('path: %s\n' %(path) )
if not os.path.exists(path):
write_log('path: %s is not exist\n' %(path) )
return (1, 'INVALID DISK ID')
return (0, path)
return (1, 'INVALID DISK ID')
# check whether disk is mount
def check_mount(diskid = ''):
mounted = False
device = []
with open('/proc/mounts','r') as f:
for l in f:
dev = l.split( )[0]
if diskid in dev:
if os.path.dirname(diskid) != os.path.dirname(dev):
continue
write_log('/proc/mounts: %s' %(l) )
write_log('device %s is mounted\n' %(dev) )
mounted = True
device.append(dev)
return (mounted,device)
def discovery_targets(ipport = '169.254.68.2:3260'):
ret = []
cmd = quote_str('iscsiadm -m discovery -t st -p ' + ipport)
write_log('%s, handle: %s\n' %(time.ctime(), cmd) )
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
return (1, ret)
if len(out) < 1:
write_log("No results\n")
return (0, ret)
for line in out:
write_log('%s' %(line) )
# FIXME. if discovery failed, perhaps no open-iscsi running or iscsi.ko
target = line.split( )[1]
write_log('get target: %s\n' %(target) )
ret.append(target)
return (0, ret)
#delete the record in iscsi-tgt after logout
def delete_record(target = ''):
cmd = quote_str('iscsiadm -m node -o delete -T ' + target)
write_log('%s, handle: %s\n' %(time.ctime(), cmd) )
try: # response of delete has no 'successful', CAN NOT use exec_cmd
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
return 0
def find_softlink(diskid = ''):
sl_path = '/dev/disk/by-id/'
for x in os.listdir(sl_path):
if 'disk-' not in x:
continue
path = os.path.join(sl_path, x)
if os.path.islink(path):
real_path = os.readlink(path)
write_log('sl_path: %s, real_path: %s\n' %(path, real_path) )
if real_path == diskid:
write_log('find softlink\n')
return (0, path)
return (1, 'NULL')
def target_match(target = ''):
pattern = r'^iqn\..+spdk:([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$'
match = re.match(pattern, target)
return bool(match)
#########################
def process_attach(target = '', volume = '', client_address = ''):
if target != '1' or volume != '2':
if client_address != "169.254.68.2":
return (1, 'IP NOT ALLOW, ATTACH FAILED')
if not target_match(target):
write_log("Error target:%s\n" % target)
return (1, 'ATTACH FAILED')
# 1. discovery
(status, targets) = discovery_targets()
if status > 0:
write_log("Error: discovery failed\n")
return (1, 'DISCOVERY FAILED')
if target not in targets:
write_log("not discovery target %s\n" % target)
return (1, 'NOT DISCOVERY TARGET')
# 2. login
already_login = False
cmd = 'iscsiadm -m node -l -T ' + target
(status, resp) = exec_cmd(cmd)
#check whether the session has been established
session = check_session(target)
if session > 0:
if status > 0:
return (1, 'LOGIN FAILED')
else:
write_log("Error: Login successful but there's no active session\n")
return (1,'LOGIN FAILED')
# if the output of login cmd is none, the session has already been established
elif status == 2:
already_login = True
# 3. check by-id
# timeout: 10ms*300 = 3s
timeout=300
count=0
write_log("Waitlink......\n")
(status, diskid) = find_diskid(target)
while (status > 0 and count < timeout):
time.sleep(0.01)
(status, diskid) = find_diskid(target)
count = count + 1
if status > 0:
cmd = 'iscsiadm -m node -u -T ' + target
(status, resp) = exec_cmd(cmd)
if status > 0:
return (1, 'DEVICE NOT FIND AND LOGOUT FAILED')
delete_record(target)
return (1, 'DEVICE NOT FIND')
# 4. check the format of volume
(device_path,device_name) = os.path.split(diskid)
(status,disk_id) = get_diskid(device_name)
if(status > 0 or disk_id != volume):
if(status > 0):
write_log("can not get legal disk_id from /sys/block/%s/device/model\n" % (device_name) )
else:
write_log("disk_id is %s, and volume is %s, input error\n" % (disk_id,volume) )
# if login just now, we should logout, delete record and return failed
if not already_login:
session = check_session(target)
if session == 0:
#if session exist, logout first
cmd = 'iscsiadm -m node -u -T ' + target
(status, resp) = exec_cmd(cmd)
if status > 0:
return (1, 'DISKID INCORRECT AND LOGOUT FAILED')
# delete record
delete_record(target)
return (1, 'DISKID INCORRECT')
# 5. set soft link and timeout and max_sector_size
dst = '/dev/disk/by-id/' + volume
set_softlink(dst,diskid)
dst = '/dev/disk/by-id/virtio-' + volume
set_softlink(dst,diskid)
if already_login:
return (0, 'ALREADY_LOGIN')
else:
return (0, 'SUCCESS')
def process_detach(target = '', forceflag = '--noforce', client_address = ''):
if client_address != "169.254.68.2":
return (1, 'IP NOT ALLOW, DETACH FAILED')
if not target_match(target):
write_log("Error target:%s\n" % target)
return (1, 'DETACH FAILED')
# 0. force or not
force = False
diskid_exist = True
softlink_exist = True
if forceflag == '--force':
force = True
# 1. find disk-id and softlink
(status, diskid) = find_diskid(target)
if status > 0:
diskid_exist = False
write_log("process_detach : Not find diskid\n")
(status, softlink) = find_softlink(diskid)
if status > 0:
softlink_exist = False
write_log("process_detach : Not find softlink\n")
# 2. check mounted
mounted = False
if(diskid_exist):
(mounted,device) = check_mount(diskid)
# 3. if mounted and force, try to umount; and not force, exit.
if mounted:
if force:
for dev in device:
cmd = quote_str('umount ' + dev)
write_log('%s, handle: %s\n' %(time.ctime(), cmd) )
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
else: # not force
write_log("%s is mounted, and not force to logout, just exit\n" % diskid)
return (0, 'MOUNTED AND NOT LOGOUT')
# 4. delete softlink
delete_softlink_flag = softlink_exist
while delete_softlink_flag:
if os.path.exists(softlink):
os.remove(softlink)
(status, softlink) = find_softlink(diskid)
if status > 0:
delete_softlink_flag = False
#5.check session
session = check_session(target)
if session > 0:
#if session not exist, just delete record
delete_record(target)
return (2,'NOTHING_TO_DO')
else:
#if session exist, logout and delete record
cmd = 'iscsiadm -m node -u -T ' + target
(status, resp) = exec_cmd(cmd)
if status > 0:
return (3, 'LOGOUT FAILED')
delete_record(target)
if not (diskid_exist and softlink_exist):
return (1, 'LOGOUT')
return (0, 'SUCCESS')
def process_rescan(target = '', client_address = ''):
if client_address != "169.254.68.2":
return (1, 'IP NOT ALLOW, RESCAN FAILED')
if not target_match(target):
write_log("Error target:%s\n" % target)
return (1, 'RESCAN FAILED')
cmd = quote_str('iscsiadm -m node -R -T ' + target)
write_log('%s, handle: %s\n' %(time.ctime(), cmd) )
try:
out = os.popen(cmd, 'r').readlines()
except OSError, e:
write_log("Error :%s\n" % e)
rescan = False
for line in out:
write_log('%s' %(line) )
if 'Rescanning' in line:
rescan = True
write_log('rescan successful\n')
if not rescan:
write_log('rescan Failed\n')
return (1, 'RESCAN FAILED')
return (0, 'SUCCESS')
def process_request(request, client_addres = ''):
args = request.split( )
if len(args) < 3:
write_log("Error: invalid arguments, %s\n" % request)
return (1, 'INVAID ARGUMENTS')
if args[0] == 'attach':
(ret, msg) = process_attach(args[1], args[2], client_addres)
elif args[0] == 'detach':
(ret, msg) = process_detach(args[1], args[2], client_addres)
elif args[0] == 'rescan':
(ret, msg) = process_rescan(args[1], client_addres)
else:
write_log("Error: invalid arguments, %s\n" % request)
return (1, 'INVAID ARGUMENTS')
return (ret, msg)
class ProxyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
conn = self.request
self.data = conn.recv(256).strip()
write_log('from [%s] recv request: %s\n' %(self.client_address, self.data) )
client_addres_str = self.client_address[0]
(eno, rsp) = process_request(self.data, client_addres_str)
write_log('(%d) response: %s\n' %(eno, rsp))
self.data = '%d+' % eno
self.data += rsp
conn.sendall(self.data.upper())
def socket_server(localip = '169.254.68.1', port = 9966):
# socket
SocketServer.TCPServer.allow_reuse_address = True
server = SocketServer.TCPServer((localip, port), ProxyTCPHandler)
write_version()
write_log("SocketServer starting...\n")
server.serve_forever()
###########################################################
# main
def main():
log_rotate()
check_os()
check_iscsi()
check_iscsi_config()
change_proc_name(proxy_name)
check_proc()
check_Ethernet()
check_eth_status()
daemonize()
creat_softlink_checker()
socket_server()
# main
if __name__ == "__main__":
main()