config_functest.py: added create neutron network.
[functest.git] / testcases / vPing / CI / libraries / vPing.py
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2015 All rights reserved. This program and the accompanying materials
4 # are made available under the terms of the Apache License, Version 2.0
5 # which accompanies this distribution, and is available at
6 #
7 #               http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # This script boots the VM1 and allocates IP address from Nova
10 # Later, the VM2 boots then execute cloud-init to ping VM1.
11 # After successful ping, both the VMs are deleted.
12 #
13 # Note: this is script works only with Ubuntu image, not with Cirros image
14 #
15
16 import os, time, subprocess, logging, argparse, yaml
17 import pprint
18 import novaclient.v2.client as novaclient
19 import neutronclient.client as neutronclient
20 #import novaclient.v1_1.client as novaclient
21 import cinderclient.v1.client as cinderclient
22 pp = pprint.PrettyPrinter(indent=4)
23
24 EXIT_CODE = -1
25 HOME = os.environ['HOME']+"/"
26 with open(HOME+'.functest/functest.yaml') as f:
27     functest_yaml = yaml.safe_load(f)
28 f.close()
29
30 PING_TIMEOUT = functest_yaml.get("vping").get("ping_timeout")
31 NAME_VM_1 = functest_yaml.get("vping").get("vm_name_1")
32 NAME_VM_2 = functest_yaml.get("vping").get("vm_name_2")
33 GLANCE_IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name")
34 NEUTRON_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_net_name")
35 FLAVOR = functest_yaml.get("vping").get("vm_flavor")
36
37
38 parser = argparse.ArgumentParser()
39 parser.add_argument("-d", "--debug", help="Debug mode",  action="store_true")
40 args = parser.parse_args()
41
42 """ logging configuration """
43 logger = logging.getLogger('vPing')
44 logger.setLevel(logging.DEBUG)
45
46 ch = logging.StreamHandler()
47 if args.debug:
48     ch.setLevel(logging.DEBUG)
49 else:
50     ch.setLevel(logging.INFO)
51 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
52 ch.setFormatter(formatter)
53 logger.addHandler(ch)
54
55
56
57 def pMsg(value):
58     """pretty printing"""
59     pp.pprint(value)
60
61 def print_title(title):
62     """Print titles"""
63     print "\n"+"#"*40+"\n# "+title+"\n"+"#"*40+"\n"
64
65 def get_credentials(service):
66     """Returns a creds dictionary filled with the following keys:
67     * username
68     * password/api_key (depending on the service)
69     * tenant_name/project_id (depending on the service)
70     * auth_url
71     :param service: a string indicating the name of the service
72                     requesting the credentials.
73     """
74     #TODO: get credentials from the openrc file
75     creds = {}
76     # Unfortunately, each of the OpenStack client will request slightly
77     # different entries in their credentials dict.
78     if service.lower() in ("nova", "cinder"):
79         password = "api_key"
80         tenant = "project_id"
81     else:
82         password = "password"
83         tenant = "tenant_name"
84
85     # The most common way to pass these info to the script is to do it through
86     # environment variables.
87     creds.update({
88         "username": os.environ.get('OS_USERNAME', "admin"),                                                             # add your cloud username details
89         password: os.environ.get("OS_PASSWORD", 'admin'),                                                               # add password
90         "auth_url": os.environ.get("OS_AUTH_URL","http://192.168.20.71:5000/v2.0"),             # Auth URL
91         tenant: os.environ.get("OS_TENANT_NAME", "admin"),
92     })
93
94     return creds
95
96
97 def get_server(creds, servername):
98     nova = novaclient.Client(**creds)
99     return nova.servers.find(name=servername)
100
101
102 def waitVmActive(nova,vm):
103     # sleep and wait for VM status change
104     while get_status(nova,vm) != "ACTIVE":
105         time.sleep(3)
106         logger.debug("Status: %s" % vm.status)
107     logger.debug("Status: %s" % vm.status)
108
109 def get_status(nova,vm):
110     vm = nova.servers.get(vm.id)
111     return vm.status
112
113
114 def main():
115     creds = get_credentials("nova")
116     nova = novaclient.Client(**creds)
117     cinder = cinderclient.Client(**creds)
118
119     """
120     # print images and server resources
121     # print nova_images
122     print_title("images list")
123     pMsg(nova.images.list())
124     print_title("servers list")
125     pMsg(nova.servers.list())
126     """
127     # Check if the given image is created
128     images=nova.images.list()
129     image_found = False
130     for image in images:
131         if image.name == GLANCE_IMAGE_NAME:
132             logger.info("Glance image found '%s'" %image.name)
133             image_found = True
134     if not image_found:
135         logger.error("ERROR: Glance image %s not found." % GLANCE_IMAGE_NAME)
136         logger.info("Available images are: ")
137         pMsg(nova.images.list())
138         exit(-1)
139
140     # Check if the given neutron network is created
141     networks=nova.networks.list()
142     network_found = False
143     for net in networks:
144         if net.human_id == NEUTRON_NET_NAME:
145             logger.info("Network found '%s'" %net.human_id)
146             network_found = True
147     if not network_found:
148         logger.error("Neutron network %s not found." % NEUTRON_NET_NAME)
149         logger.info("Available networks are: ")
150         pMsg(nova.networks.list())
151         exit(-1)
152
153     servers=nova.servers.list()
154     for server in servers:
155         if server.name == NAME_VM_1 or server.name == NAME_VM_2:
156             logger.info("Instance %s found. Deleting..." %server.name)
157             server.delete()
158
159
160
161     # boot VM 1
162     # basic boot
163   # tune (e.g. flavor, images, network) to your specific openstack configuration here
164     m = NAME_VM_1
165     f = nova.flavors.find(name = FLAVOR)
166     i = nova.images.find(name = GLANCE_IMAGE_NAME)
167     n = nova.networks.find(label = NEUTRON_NET_NAME)
168     u = "#cloud-config\npassword: opnfv\nchpasswd: { expire: False }\nssh_pwauth: True"
169     #k = "demo-key"
170
171     # create VM
172     logger.info("Creating instance '%s'..." %m)
173     logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(m,f,i,n,u))
174     vm1 = nova.servers.create(
175         name               = m,
176         flavor             = f,
177         image              = i,
178         nics               = [{"net-id": n.id}],
179         #key_name           = k,
180         userdata           = u,
181     )
182
183     #pMsg(vm1)
184
185
186     #wait until VM status is active
187     waitVmActive(nova,vm1)
188
189     #retrieve IP of first VM
190     logger.debug("Fetching IP...")
191     server = get_server(creds, m)
192     #pMsg(server.networks)
193     # theoretically there is only one IP address so we take the first element of the table
194     # Dangerous! To be improved!
195     test_ip = server.networks.get(NEUTRON_NET_NAME)[0]
196     logger.debug("Instance '%s' got %s" %(m,test_ip))
197     test_cmd = '/tmp/vping.sh %s'%test_ip
198
199
200     # boot VM 2
201     # we will boot then execute a ping script with cloud-init
202     # the long chain corresponds to the ping procedure converted with base 64
203   # tune (e.g. flavor, images, network) to your specific openstack configuration here
204     m = NAME_VM_2
205     f = nova.flavors.find(name = FLAVOR)
206     i = nova.images.find(name = GLANCE_IMAGE_NAME)
207     n = nova.networks.find(label = NEUTRON_NET_NAME)
208     # use base 64 format becaus bad surprises with sh script with cloud-init but script is just pinging
209     #k = "demo-key"
210     u = "#cloud-config\npassword: opnfv\nchpasswd: { expire: False }\nssh_pwauth: True\nwrite_files:\n-  encoding: b64\n   path: /tmp/vping.sh\n   permissions: '0777'\n   owner: root:root\n   content: IyEvYmluL2Jhc2gKCndoaWxlIHRydWU7IGRvCiBwaW5nIC1jIDEgJDEgMj4mMSA+L2Rldi9udWxsCiBSRVM9JD8KIGlmIFsgIlokUkVTIiA9ICJaMCIgXSA7IHRoZW4KICBlY2hvICJ2UGluZyBPSyIKICBzbGVlcCAxMAogIHN1ZG8gc2h1dGRvd24gLWggbm93CiAgYnJlYWsKIGVsc2UKICBlY2hvICJ2UGluZyBLTyIKIGZpCiBzbGVlcCAxCmRvbmUK\nruncmd:\n - [ sh, -c, %s]"%test_cmd
211     # create VM
212     logger.info("Creating instance '%s'..." %m)
213     logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(m,f,i,n,u))
214     vm2 = nova.servers.create(
215         name               = m,
216         flavor             = f,
217         image              = i,
218         nics               = [{"net-id": n.id}],
219         #key_name           = k,
220         userdata           = u,
221         #security_groups    = s,
222         #config_drive       = v.id
223     )
224     # The injected script will shutdown the VM2 when the ping works
225     # The console-log method is more consistent but doesn't work yet
226
227     waitVmActive(nova,vm2)
228
229     logger.info("Waiting for ping, timeout is %d sec..." % PING_TIMEOUT)
230     sec = 0
231     while True:
232         status = get_status(nova, vm2)
233         #print status
234         if status == "SHUTOFF" :
235             EXIT_CODE = 0
236             logger.info("vPing SUCCESSFUL after %d sec" % sec)
237             break
238         if sec == PING_TIMEOUT:
239             logger.info("Timeout. vPing UNSUCCESSFUL.")
240             break
241         time.sleep(1)
242         sec+=1
243
244     """
245     # I leave this here until we fix the console-log output
246     sec = 0
247     console_log = vm2.get_console_output()
248     while not ("vPing" in console_log):
249         time.sleep(1)
250         console_log = vm2.get_console_output()
251         print "--"+console_log
252
253         # report if the test is failed
254         if "vPing" in console_log:
255             pMsg("vPing is OK")
256             break
257         else:
258             pMsg("no vPing detected....")
259         sec+=1
260         if sec == PING_TIMEOUT:
261             break
262     """
263
264     # delete both VMs
265     logger.debug("Deleting Instances...")
266     nova.servers.delete(vm1)
267     logger.debug("Instance %s terminated." % NAME_VM_1)
268     nova.servers.delete(vm2)
269     logger.debug("Instance %s terminated." % NAME_VM_2)
270
271
272     logger.debug("EXIT_CODE=%s" % EXIT_CODE)
273     exit(EXIT_CODE)
274
275
276 if __name__ == '__main__':
277     main()