summaryrefslogtreecommitdiffstats
path: root/vstf/vstf/agent/env/fsmonitor
diff options
context:
space:
mode:
Diffstat (limited to 'vstf/vstf/agent/env/fsmonitor')
-rwxr-xr-xvstf/vstf/agent/env/fsmonitor/FSMonitor.py215
-rwxr-xr-xvstf/vstf/agent/env/fsmonitor/Readme13
-rwxr-xr-xvstf/vstf/agent/env/fsmonitor/__init__.py14
-rwxr-xr-xvstf/vstf/agent/env/fsmonitor/constant.py17
-rwxr-xr-xvstf/vstf/agent/env/fsmonitor/utils.py110
5 files changed, 369 insertions, 0 deletions
diff --git a/vstf/vstf/agent/env/fsmonitor/FSMonitor.py b/vstf/vstf/agent/env/fsmonitor/FSMonitor.py
new file mode 100755
index 00000000..71029705
--- /dev/null
+++ b/vstf/vstf/agent/env/fsmonitor/FSMonitor.py
@@ -0,0 +1,215 @@
+"""
+Created on 2015-7-13
+
+@author: y00228926
+"""
+import os
+import time
+import logging
+import subprocess
+import sys
+
+import constant
+from utils import IPCommandHelper, umount, check_and_rmmod, check_output, check_call, call
+
+LOG_FILE = '/tmp/fsmonitor.log'
+PID_FILE = '/tmp/fsmonitor.pid'
+LOG = logging.getLogger('__name__')
+
+
+class VMOperation(object):
+ def __init__(self):
+ self.RTE_SDK = '/home/dpdk-2.0.0'
+ self.RTE_TARGET = 'x86_64-native-linuxapp-gcc'
+ self.nr_hugepages = '512'
+ self.pid = 0
+ self.ip_helper = IPCommandHelper()
+
+ def config_ip(self, mac, ip):
+ device = self.ip_helper.mac_device_map[mac]
+ check_call("ifconfig %s %s up" % (device, ip), shell=True)
+
+ def config_gw(self, ip):
+ call("route del default", shell=True)
+ check_call("route add default gw %s" % ip, shell=True)
+
+ def recover_nic_binding(self, *tap_macs):
+ if self.pid:
+ os.kill(self.pid, 9)
+ self.pid = None
+ bdf_str = ''
+ for mac in tap_macs:
+ bdf = self.ip_helper.mac_bdf_map[mac]
+ bdf_str = bdf_str + ' ' + bdf
+ cmd = 'python %s/tools/dpdk_nic_bind.py --bind=virtio-pci %s' % (self.RTE_SDK, bdf_str)
+ LOG.debug("recover_nic_binding runs cmd = %s", cmd)
+ check_call(cmd, shell=True)
+
+ def set_pktloop_dpdk(self, *tap_macs):
+ RTE_SDK = self.RTE_SDK
+ RTE_TARGET = self.RTE_TARGET
+ umount("/mnt/huge")
+ with open('/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages', 'w') as f:
+ f.write(self.nr_hugepages)
+ check_call("mkdir -p /mnt/huge", shell=True)
+ check_call("mount -t hugetlbfs nodev /mnt/huge", shell=True)
+ check_call("modprobe uio", shell=True)
+ check_and_rmmod('igb_uio')
+ check_call("insmod %s/%s/kmod/igb_uio.ko" % (RTE_SDK, RTE_TARGET), shell=True)
+
+ bdf_str = ''
+ for mac in tap_macs:
+ bdf = self.ip_helper.mac_bdf_map[mac]
+ bdf_str = bdf_str + ' ' + bdf
+
+ check_call('python %s/tools/dpdk_nic_bind.py --bind=igb_uio %s' % (RTE_SDK, bdf_str), shell=True)
+ cpu_num = int(check_output('cat /proc/cpuinfo | grep processor | wc -l', shell=True))
+ cpu_bit_mask = 0
+ i = cpu_num
+ while i:
+ cpu_bit_mask = (cpu_bit_mask << 1) + 1
+ i -= 1
+ cpu_bit_mask = hex(cpu_bit_mask)
+ cmd = "%s/%s/app/testpmd -c %s -n %d -- --disable-hw-vlan --disable-rss --nb-cores=%d --rxq=%d --txq=%d --rxd=4096 --txd=4096" % (
+ RTE_SDK,
+ RTE_TARGET,
+ cpu_bit_mask,
+ cpu_num / 2,
+ cpu_num - 1,
+ (cpu_num - 1) / 2,
+ (cpu_num - 1) / 2
+ )
+ LOG.info("set_pktloop_dpdk runs cmd = %s", cmd)
+ p = subprocess.Popen(cmd.split())
+ if not p.poll():
+ self.pid = p.pid
+ return True
+ else:
+ raise Exception("start testpmd failed")
+
+ def config_amqp(self, file_name):
+ if not os.path.isfile(file_name):
+ raise Exception("file: %s not exists." % file_name)
+ check_call("cp %s /etc/vstf/amqp/amqp.ini" % file_name, shell=True)
+ check_call("vstf-agent restart", shell=True)
+ return True
+
+ def stop_vstf(self):
+ check_call("vstf-agent stop", shell=True)
+ return True
+
+
+class FSMonitor(object):
+ def __init__(self, pidfile=None, interval=1):
+ if pidfile:
+ self.pidfile = pidfile
+ else:
+ self.pidfile = PID_FILE
+ self.interval = interval
+ self.handlers = []
+ self.kill_old()
+ umount(constant.FS_MOUNT_POINT)
+ check_call("mkdir -p %s" % constant.FS_MOUNT_POINT, shell=True)
+ check_call("mount -t 9p 9pfs %s" % constant.FS_MOUNT_POINT, shell=True)
+ os.chdir(constant.FS_MOUNT_POINT)
+ with open(constant.VM_UP_Flag_FILE, 'w'):
+ pass
+
+ def kill_old(self):
+ out = check_output("ps -ef | grep -v grep | egrep 'python.*%s' | awk '{print $2}'" % sys.argv[0],
+ shell=True)
+ if out:
+ for pid in out.split():
+ if int(pid) != os.getpid():
+ os.kill(int(pid), 9)
+ LOG.debug("found daemon:pid=%s and kill.", pid)
+
+ def set_fail(self, failed_reason):
+ with open(constant.VM_CMD_RETURN_CODE_FILE, 'w') as f:
+ f.writelines([constant.VM_CMD_EXCUTE_FAILED_FLAG_CONTENT, '\n', failed_reason])
+ with open(constant.VM_CMD_DONE_FLAG_FILE, 'w') as f:
+ pass
+
+ def set_success(self):
+ with open(constant.VM_CMD_RETURN_CODE_FILE, 'w') as f:
+ f.write(constant.VM_CMD_EXCUTE_SUCCES_FLAG_CONTENT)
+ with open(constant.VM_CMD_DONE_FLAG_FILE, 'w') as f:
+ pass
+
+ def register_handler(self, obj):
+ self.handlers.append(obj)
+
+ def daemonize(self):
+ try:
+ pid = os.fork()
+ if pid > 0:
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write('fork #1 failed:%d,(%s)\n' % (e.errno, e.strerror))
+ sys.exit(1)
+ os.setsid()
+ os.umask(0)
+ try:
+ pid = os.fork()
+ if pid > 0:
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write('fork #2 failed:%d,(%s)\n' % (e.errno, e.strerror))
+ sys.exit(1)
+ LOG.debug("pid:%d,ppid:%d,sid:%d", os.getpid(), os.getppid(), os.getsid(os.getpid()))
+ old = open('/dev/null', 'r')
+ os.dup2(old.fileno(), sys.stdin.fileno())
+ old = open('/dev/null', 'a+')
+ os.dup2(old.fileno(), sys.stdout.fileno())
+ old = open('/dev/null', 'a+', 0)
+ os.dup2(old.fileno(), sys.stderr.fileno())
+ pid = str(os.getpid())
+ file(self.pidfile, 'w+').write('%s\n' % pid)
+
+ def run_forever(self):
+ # todo:resolve handlers name space conflict
+ self.daemonize()
+ while True:
+ time.sleep(self.interval)
+ files = os.listdir(constant.FS_MOUNT_POINT)
+ if constant.VM_CMD_SET_FLAG_FILE in files and constant.VM_CMD_CONTENT_FILE in files:
+ with open(constant.VM_CMD_CONTENT_FILE, 'r') as f:
+ out = f.read().strip()
+ LOG.debug("new command arrived:%s", out)
+ cmd_param = out.split()
+ cmd = cmd_param[0]
+ param = cmd_param[1:]
+ for obj in self.handlers:
+ if hasattr(obj, cmd) and callable(getattr(obj, cmd)):
+ LOG.debug("method:%s found!", cmd)
+ method = getattr(obj, cmd)
+ try:
+ method(*param)
+ self.set_success()
+ LOG.debug("cmd sucessfully done")
+ except Exception, e:
+ LOG.debug('failed to run:%s %s,reason:%s', cmd, param, str(e))
+ self.set_fail(str(e))
+ break
+ else:
+ LOG.debug("method:%s not found!", cmd)
+ self.set_fail(constant.VM_CMD_NOT_FOUND)
+ os.remove(constant.VM_CMD_SET_FLAG_FILE)
+ os.remove(constant.VM_CMD_CONTENT_FILE)
+
+
+if __name__ == '__main__':
+ # echo "set_pktloop_dpdk" > command;touch command_set
+ # echo "recover_nic_binding" > command;touch command_set
+ # echo "config_ip 56:6f:44:a5:3f:a2 192.168.188.200/23" > command;touch command_set
+ # echo "config_gw 192.168.188.1" > command;touch command_set
+ # echo set_pktloop_dpdk 56:6f:44:a5:3f:a2 56:6f:44:a5:3f:a3 > command;touch command_set
+ # echo recover_nic_binding 56:6f:44:a5:3f:a2 56:6f:44:a5:3f:a3 > command;touch command_set
+ import os
+ logging.basicConfig(level=logging.DEBUG, filename=LOG_FILE, filemode='w')
+ os.environ['PATH'] = os.environ["PATH"] + ":/usr/local/bin"
+ LOG.info(os.environ['PATH'])
+ vm_op = VMOperation()
+ agent = FSMonitor()
+ agent.register_handler(vm_op)
+ agent.run_forever()
diff --git a/vstf/vstf/agent/env/fsmonitor/Readme b/vstf/vstf/agent/env/fsmonitor/Readme
new file mode 100755
index 00000000..f2bf9a8e
--- /dev/null
+++ b/vstf/vstf/agent/env/fsmonitor/Readme
@@ -0,0 +1,13 @@
+FSMonitor is a daemon process which runs in the vm.
+FSMonitor receive "commands" from 'VmManager' by libvirt 9pfs.
+
+Basically the process works like this:
+ 1.The 'VmManager' writes 'command string' to 'command' file on the libvirt 9pfs used by vm.
+ 2.The FSMonitor constantly detects file changes on the libvirt 9pfs.
+ 3.The FSMonitor finds the newly created file, it then reads the file and execute the command.
+
+All the dependencies of FSMonitor should be satisfied by modules in this directory.
+
+When deploying FSMonitor, just copy this directory into the vm.
+
+
diff --git a/vstf/vstf/agent/env/fsmonitor/__init__.py b/vstf/vstf/agent/env/fsmonitor/__init__.py
new file mode 100755
index 00000000..89dcd4e2
--- /dev/null
+++ b/vstf/vstf/agent/env/fsmonitor/__init__.py
@@ -0,0 +1,14 @@
+# Copyright Huawei Technologies Co., Ltd. 1998-2015.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the License); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
diff --git a/vstf/vstf/agent/env/fsmonitor/constant.py b/vstf/vstf/agent/env/fsmonitor/constant.py
new file mode 100755
index 00000000..d30bb439
--- /dev/null
+++ b/vstf/vstf/agent/env/fsmonitor/constant.py
@@ -0,0 +1,17 @@
+"""
+Created on 2015-8-27
+
+@author: y00228926
+"""
+VM_UP_Flag_FILE = 'up'
+VM_CMD_DONE_FLAG_FILE = 'command_done'
+VM_CMD_RESULT_FILE = 'command_result_data'
+VM_CMD_SET_FLAG_FILE = 'command_set'
+VM_CMD_CONTENT_FILE = 'command'
+VM_CMD_RETURN_CODE_FILE = 'command_result'
+VM_CMD_EXCUTE_SUCCES_FLAG_CONTENT = 'success'
+VM_CMD_EXCUTE_FAILED_FLAG_CONTENT = 'fail'
+VM_CMD_NOT_FOUND = 'comamnd_not_found'
+VM_UP_TIME_OUT = 120
+VM_COMMON_CMD_EXCUTE_TIME_OUT = 10
+FS_MOUNT_POINT = '/mnt/9pfs' \ No newline at end of file
diff --git a/vstf/vstf/agent/env/fsmonitor/utils.py b/vstf/vstf/agent/env/fsmonitor/utils.py
new file mode 100755
index 00000000..e6eb1536
--- /dev/null
+++ b/vstf/vstf/agent/env/fsmonitor/utils.py
@@ -0,0 +1,110 @@
+"""
+Created on 2015-7-8
+
+@author: y00228926
+"""
+import subprocess
+from StringIO import StringIO
+import re
+import logging
+
+LOG = logging.getLogger(__name__)
+
+
+def call(cmd, shell=False):
+ if shell:
+ LOG.info(cmd)
+ else:
+ LOG.info(' '.join(cmd))
+ return subprocess.call(cmd, shell=shell)
+
+
+def check_call(cmd, shell=False):
+ if shell:
+ LOG.info(cmd)
+ else:
+ LOG.info(' '.join(cmd))
+ subprocess.check_call(cmd, shell=shell)
+
+
+def check_output(cmd, shell=False):
+ if shell:
+ LOG.info(cmd)
+ else:
+ LOG.info(' '.join(cmd))
+ return subprocess.check_output(cmd, shell=shell)
+
+
+def check_and_kill(process):
+ cmd = "ps -ef | grep -v grep | awk '{print $8}' | grep -w %s | wc -l" % process
+ out = check_output(cmd, shell=True)
+ if int(out):
+ check_call(['killall', process])
+
+
+def check_and_rmmod(mod):
+ cmd = "lsmod | awk '{print $1}' | grep -w %s | wc -l" % mod
+ out = check_output(cmd, shell=True)
+ if int(out):
+ check_call(['rmmod', mod])
+
+
+def umount(path):
+ mount_path_set = set()
+ out = check_output("cat /proc/mounts", shell=True)
+ f = StringIO(out)
+ line = f.readline()
+ while line:
+ line = f.readline()
+ if line:
+ mpath = line.split()[1]
+ mount_path_set.add(mpath)
+ if path in mount_path_set:
+ ret = call("umount %s" % path, shell=True)
+ return ret == 0
+ return True
+
+
+class IPCommandHelper(object):
+ def __init__(self):
+ self.devices = []
+ self.macs = []
+ self.device_mac_map = {}
+ self.mac_device_map = {}
+ self.bdf_device_map = {}
+ self.device_bdf_map = {}
+ self.mac_bdf_map = {}
+ self.bdf_mac_map = {}
+ buf = check_output("ip link", shell=True)
+ macs = re.compile("[A-F0-9]{2}(?::[A-F0-9]{2}){5}", re.IGNORECASE | re.MULTILINE)
+ for mac in macs.findall(buf):
+ if mac.lower() in ('00:00:00:00:00:00', 'ff:ff:ff:ff:ff:ff'):
+ continue
+ self.macs.append(mac)
+ sio = StringIO(buf)
+ for line in sio:
+ m = re.match(r'^\d+:(.*):.*', line)
+ if m and m.group(1).strip() != 'lo':
+ self.devices.append(m.group(1).strip())
+ for device, mac in zip(self.devices, self.macs):
+ self.device_mac_map[device] = mac
+ self.mac_device_map[mac] = device
+ for device in self.devices:
+ buf = check_output("ethtool -i %s" % device, shell=True)
+ bdfs = re.findall(r'^bus-info: \d{4}:(\d{2}:\d{2}\.\d*)$', buf, re.MULTILINE)
+ if bdfs:
+ self.bdf_device_map[bdfs[0]] = device
+ self.device_bdf_map[device] = bdfs[0]
+ mac = self.device_mac_map[device]
+ self.mac_bdf_map[mac] = bdfs[0]
+ self.bdf_mac_map[bdfs[0]] = mac
+
+
+if __name__ == '__main__':
+ ip_helper = IPCommandHelper()
+ print ip_helper.device_mac_map
+ print ip_helper.mac_device_map
+ print ip_helper.bdf_device_map
+ print ip_helper.device_bdf_map
+ print ip_helper.mac_bdf_map
+ print ip_helper.bdf_mac_map