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