JIRA: BOTTLENECKS-29
[bottlenecks.git] / vstf / vstf / agent / env / basic / vm9pfs.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 import os
11 import logging
12 import textwrap
13 from vstf.common.utils import my_sleep
14 from vstf.agent.env.fsmonitor import constant
15
16 LOG = logging.getLogger(__name__)
17
18
19 class VMConfigBy9pfs(object):
20     """
21     host side implemetation of a self-defined communication protocol using libvirt 9pfs to give commands to the Virtual Machine.
22
23     """
24
25     def __init__(self, vm_9p_path):
26         """
27         :param vm_9p_path: The host path of libvirt 9pfs for a vm.
28         :return:
29         """
30         self.vm_9p_path = vm_9p_path
31
32     def clean(self):
33         self._unlink(self._path(constant.VM_CMD_RETURN_CODE_FILE))
34         self._unlink(self._path(constant.VM_CMD_DONE_FLAG_FILE))
35
36     def _path(self, relative_path):
37         return os.path.join(self.vm_9p_path, relative_path)
38
39     def _unlink(self, file_path):
40         os.unlink(file_path)
41         LOG.info("os.unlink(%s)", file_path)
42
43     def _read(self, filename):
44         filepath = self._path(filename)
45         with open(filepath, 'r') as f:
46             ret = f.read()
47             LOG.info("read(%s) -> %s", filepath, ret)
48         return ret
49
50     def _write(self, filename, cmd):
51         filepath = self._path(filename)
52         with open(filepath, 'w') as f:
53             f.write("%s" % cmd)
54             LOG.info("write(%s) <- %s", filepath, cmd)
55
56     def _wait_flag_file_to_exist(self, filename, timeout):
57         filepath = self._path(filename)
58         while timeout > 0:
59             if os.path.exists(filepath):
60                 LOG.info("wait and find file:%s", filepath)
61                 return True
62             my_sleep(1)
63             timeout -= 1
64             LOG.info("waiting file to exist:%s", filepath)
65         return False
66
67     def _get_cmd_return_code(self):
68         ret = self._read(constant.VM_CMD_RETURN_CODE_FILE)
69         return ret == constant.VM_CMD_EXCUTE_SUCCES_FLAG_CONTENT
70
71     def _wait_command_done(self):
72         done = self._wait_flag_file_to_exist(constant.VM_CMD_DONE_FLAG_FILE, constant.VM_COMMON_CMD_EXCUTE_TIME_OUT)
73         if done:
74             return self._get_cmd_return_code()
75         else:
76             return 'timeout'
77
78     def _set_cmd(self, cmd):
79         self._write(constant.VM_CMD_CONTENT_FILE, cmd)
80         self._write(constant.VM_CMD_SET_FLAG_FILE, '')
81         ret = self._wait_command_done()
82         if ret:
83             self.clean()
84             return ret
85         else:
86             raise Exception("9pfs command failure: timeout.")
87
88     def wait_up(self):
89         return self._wait_flag_file_to_exist(constant.VM_UP_Flag_FILE, constant.VM_UP_TIME_OUT)
90
91     def config_ip(self, mac, ip):
92         cmd = 'config_ip %s %s' % (mac, ip)
93         return self._set_cmd(cmd)
94
95     def config_gw(self, ip):
96         cmd = 'config_gw %s' % ip
97         return self._set_cmd(cmd)
98
99     def set_pktloop_dpdk(self, macs):
100         """
101         To connect two network devices together in the vm and loop the packets received to another.
102         Use dpdk testpmd to loop the packets. See FSMonitor.
103
104         :param macs: the mac address list of network cards of the vm.
105         :return: True for success, Exception for Failure.
106         """
107         mac_str = ' '.join(macs)
108         cmd = 'set_pktloop_dpdk ' + mac_str
109         return self._set_cmd(cmd)
110
111     def recover_nic_binding(self, macs):
112         """
113         in contrast to set_pktloop_dpdk, disconnect the looping.
114         :param macs:  the mac address list of network cards of the vm.
115         :return: True for success, Exception for Failure.
116         """
117         mac_str = ' '.join(macs)
118         cmd = 'recover_nic_binding ' + mac_str
119         return self._set_cmd(cmd)
120
121     def config_amqp(self, identity, server, port=5672, user="guest", passwd="guest"):
122         data = {
123             'server': server,
124             'port': port,
125             'id': identity,
126             'user': user,
127             'passwd': passwd
128         }
129         header = "[rabbit]"
130         content = '''
131         user=%(user)s
132         passwd=%(passwd)s
133         host=%(server)s
134         port=%(port)s
135         id=%(id)s''' % data
136         file_name = "amqp.ini"
137         dedented_text = textwrap.dedent(content)
138         self._write(file_name, header+dedented_text)
139         cmd = 'config_amqp %s' % file_name
140         return self._set_cmd(cmd)
141
142     def stop_vstf(self):
143         cmd = "stop_vstf"
144         return self._set_cmd(cmd)
145
146     def __repr__(self):
147         return self.__class__.__name__ + ':' + self.vm_9p_path
148
149
150 if __name__ == '__main__':
151     fs = VMConfigBy9pfs('/tmp/tmp4T6p7L')
152     print os.listdir(os.curdir)
153     print fs.config_ip('56:6f:44:a5:3f:a4', '192.168.188.200/23')
154     print fs.config_gw('192.168.188.1')
155     print fs.set_pktloop_dpdk(['56:6f:44:a5:3f:a2', '56:6f:44:a5:3f:a3'])
156     print fs.recover_nic_binding(['56:6f:44:a5:3f:a2', '56:6f:44:a5:3f:a3'])
157     print fs.config_amqp('192.168.188.200', '192.168.188.10')
158     print os.listdir(os.curdir)