Merge "Change PTL informatin in INFO"
[bottlenecks.git] / testsuites / vstf / vstf_scripts / vstf / agent / env / fsmonitor / FSMonitor.py
1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10
11 import os
12 import time
13 import logging
14 import subprocess
15 import sys
16
17 import constant
18 from utils import IPCommandHelper, umount, check_and_rmmod, check_output, check_call, call
19
20 LOG_FILE = '/tmp/fsmonitor.log'
21 PID_FILE = '/tmp/fsmonitor.pid'
22 LOG = logging.getLogger('__name__')
23
24
25 class VMOperation(object):
26
27     def __init__(self):
28         self.RTE_SDK = '/home/dpdk-2.0.0'
29         self.RTE_TARGET = 'x86_64-native-linuxapp-gcc'
30         self.nr_hugepages = '512'
31         self.pid = 0
32         self.ip_helper = IPCommandHelper()
33
34     def config_ip(self, mac, ip):
35         device = self.ip_helper.mac_device_map[mac]
36         check_call("ifconfig %s %s up" % (device, ip), shell=True)
37
38     def config_gw(self, ip):
39         call("route del default", shell=True)
40         check_call("route add default gw %s" % ip, shell=True)
41
42     def recover_nic_binding(self, *tap_macs):
43         if self.pid:
44             os.kill(self.pid, 9)
45             self.pid = None
46         bdf_str = ''
47         for mac in tap_macs:
48             bdf = self.ip_helper.mac_bdf_map[mac]
49             bdf_str = bdf_str + ' ' + bdf
50         cmd = 'python %s/tools/dpdk_nic_bind.py --bind=virtio-pci %s' % (
51             self.RTE_SDK, bdf_str)
52         LOG.debug("recover_nic_binding runs cmd = %s", cmd)
53         check_call(cmd, shell=True)
54
55     def set_pktloop_dpdk(self, *tap_macs):
56         RTE_SDK = self.RTE_SDK
57         RTE_TARGET = self.RTE_TARGET
58         umount("/mnt/huge")
59         with open('/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages', 'w') as f:
60             f.write(self.nr_hugepages)
61         check_call("mkdir -p /mnt/huge", shell=True)
62         check_call("mount -t hugetlbfs nodev /mnt/huge", shell=True)
63         check_call("modprobe uio", shell=True)
64         check_and_rmmod('igb_uio')
65         check_call(
66             "insmod %s/%s/kmod/igb_uio.ko" %
67             (RTE_SDK, RTE_TARGET), shell=True)
68
69         bdf_str = ''
70         for mac in tap_macs:
71             bdf = self.ip_helper.mac_bdf_map[mac]
72             bdf_str = bdf_str + ' ' + bdf
73
74         check_call(
75             'python %s/tools/dpdk_nic_bind.py --bind=igb_uio %s' %
76             (RTE_SDK, bdf_str), shell=True)
77         cpu_num = int(
78             check_output(
79                 'cat /proc/cpuinfo | grep processor | wc -l',
80                 shell=True))
81         cpu_bit_mask = 0
82         i = cpu_num
83         while i:
84             cpu_bit_mask = (cpu_bit_mask << 1) + 1
85             i -= 1
86         cpu_bit_mask = hex(cpu_bit_mask)
87         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" % (
88             RTE_SDK, RTE_TARGET, cpu_bit_mask, cpu_num / 2, cpu_num - 1, (cpu_num - 1) / 2, (cpu_num - 1) / 2)
89         LOG.info("set_pktloop_dpdk runs cmd = %s", cmd)
90         p = subprocess.Popen(cmd.split())
91         if not p.poll():
92             self.pid = p.pid
93             return True
94         else:
95             raise Exception("start testpmd failed")
96
97     def config_amqp(self, file_name):
98         if not os.path.isfile(file_name):
99             raise Exception("file: %s not exists." % file_name)
100         check_call("cp %s /etc/vstf/amqp/amqp.ini" % file_name, shell=True)
101         check_call("vstf-agent restart", shell=True)
102         return True
103
104     def stop_vstf(self):
105         check_call("vstf-agent stop", shell=True)
106         return True
107
108
109 class FSMonitor(object):
110
111     def __init__(self, pidfile=None, interval=1):
112         if pidfile:
113             self.pidfile = pidfile
114         else:
115             self.pidfile = PID_FILE
116         self.interval = interval
117         self.handlers = []
118         self.kill_old()
119         umount(constant.FS_MOUNT_POINT)
120         check_call("mkdir -p %s" % constant.FS_MOUNT_POINT, shell=True)
121         check_call("mount -t 9p 9pfs %s" % constant.FS_MOUNT_POINT, shell=True)
122         os.chdir(constant.FS_MOUNT_POINT)
123         with open(constant.VM_UP_Flag_FILE, 'w'):
124             pass
125
126     def kill_old(self):
127         out = check_output(
128             "ps -ef | grep -v grep | egrep 'python.*%s' | awk '{print $2}'" %
129             sys.argv[0], shell=True)
130         if out:
131             for pid in out.split():
132                 if int(pid) != os.getpid():
133                     os.kill(int(pid), 9)
134                     LOG.debug("found daemon:pid=%s and kill.", pid)
135
136     def set_fail(self, failed_reason):
137         with open(constant.VM_CMD_RETURN_CODE_FILE, 'w') as f:
138             f.writelines(
139                 [constant.VM_CMD_EXCUTE_FAILED_FLAG_CONTENT, '\n', failed_reason])
140         with open(constant.VM_CMD_DONE_FLAG_FILE, 'w') as f:
141             pass
142
143     def set_success(self):
144         with open(constant.VM_CMD_RETURN_CODE_FILE, 'w') as f:
145             f.write(constant.VM_CMD_EXCUTE_SUCCES_FLAG_CONTENT)
146         with open(constant.VM_CMD_DONE_FLAG_FILE, 'w') as f:
147             pass
148
149     def register_handler(self, obj):
150         self.handlers.append(obj)
151
152     def daemonize(self):
153         try:
154             pid = os.fork()
155             if pid > 0:
156                 sys.exit(0)
157         except OSError as e:
158             sys.stderr.write(
159                 'fork #1 failed:%d,(%s)\n' %
160                 (e.errno, e.strerror))
161             sys.exit(1)
162         os.setsid()
163         os.umask(0)
164         try:
165             pid = os.fork()
166             if pid > 0:
167                 sys.exit(0)
168         except OSError as e:
169             sys.stderr.write(
170                 'fork #2 failed:%d,(%s)\n' %
171                 (e.errno, e.strerror))
172             sys.exit(1)
173         LOG.debug(
174             "pid:%d,ppid:%d,sid:%d",
175             os.getpid(),
176             os.getppid(),
177             os.getsid(
178                 os.getpid()))
179         old = open('/dev/null', 'r')
180         os.dup2(old.fileno(), sys.stdin.fileno())
181         old = open('/dev/null', 'a+')
182         os.dup2(old.fileno(), sys.stdout.fileno())
183         old = open('/dev/null', 'a+', 0)
184         os.dup2(old.fileno(), sys.stderr.fileno())
185         pid = str(os.getpid())
186         file(self.pidfile, 'w+').write('%s\n' % pid)
187
188     def run_forever(self):
189         # todo:resolve handlers name space conflict
190         self.daemonize()
191         while True:
192             time.sleep(self.interval)
193             files = os.listdir(constant.FS_MOUNT_POINT)
194             if constant.VM_CMD_SET_FLAG_FILE in files and constant.VM_CMD_CONTENT_FILE in files:
195                 with open(constant.VM_CMD_CONTENT_FILE, 'r') as f:
196                     out = f.read().strip()
197                 LOG.debug("new command arrived:%s", out)
198                 cmd_param = out.split()
199                 cmd = cmd_param[0]
200                 param = cmd_param[1:]
201                 for obj in self.handlers:
202                     if hasattr(obj, cmd) and callable(getattr(obj, cmd)):
203                         LOG.debug("method:%s found!", cmd)
204                         method = getattr(obj, cmd)
205                         try:
206                             method(*param)
207                             self.set_success()
208                             LOG.debug("cmd sucessfully done")
209                         except Exception as e:
210                             LOG.debug(
211                                 'failed to run:%s %s,reason:%s', cmd, param, str(e))
212                             self.set_fail(str(e))
213                         break
214                 else:
215                     LOG.debug("method:%s not found!", cmd)
216                     self.set_fail(constant.VM_CMD_NOT_FOUND)
217                 os.remove(constant.VM_CMD_SET_FLAG_FILE)
218                 os.remove(constant.VM_CMD_CONTENT_FILE)
219
220
221 if __name__ == '__main__':
222     # echo "set_pktloop_dpdk" > command;touch command_set
223     # echo "recover_nic_binding" > command;touch command_set
224     # echo "config_ip 56:6f:44:a5:3f:a2 192.168.188.200/23" > command;touch command_set
225     # echo "config_gw 192.168.188.1" > command;touch command_set
226     # echo set_pktloop_dpdk 56:6f:44:a5:3f:a2 56:6f:44:a5:3f:a3 > command;touch command_set
227     # echo recover_nic_binding 56:6f:44:a5:3f:a2 56:6f:44:a5:3f:a3 >
228     # command;touch command_set
229     import os
230     logging.basicConfig(level=logging.DEBUG, filename=LOG_FILE, filemode='w')
231     os.environ['PATH'] = os.environ["PATH"] + ":/usr/local/bin"
232     LOG.info(os.environ['PATH'])
233     vm_op = VMOperation()
234     agent = FSMonitor()
235     agent.register_handler(vm_op)
236     agent.run_forever()