3 # Copyright (c) 2015 All rights reserved
4 # 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
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # 0.1: This script boots the VM1 and allocates IP address from Nova
11 # Later, the VM2 boots then execute cloud-init to ping VM1.
12 # After successful ping, both the VMs are deleted.
13 # 0.2: measure test duration and publish results under json format
14 # 0.3: adapt push 2 DB after Test API refacroting
25 from scp import SCPClient
27 from novaclient import client as novaclient
28 from neutronclient.v2_0 import client as neutronclient
29 from keystoneclient.v2_0 import client as keystoneclient
30 from glanceclient import client as glanceclient
32 import functest.utils.functest_logger as ft_logger
33 import functest.utils.functest_utils as functest_utils
34 import functest.utils.openstack_utils as openstack_utils
36 pp = pprint.PrettyPrinter(indent=4)
38 parser = argparse.ArgumentParser()
41 parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
42 parser.add_argument("-r", "--report",
43 help="Create json result file",
46 args = parser.parse_args()
48 """ logging configuration """
49 logger = ft_logger.Logger("vping_ssh").getLogger()
51 paramiko.util.log_to_file("/var/log/paramiko.log")
53 REPO_PATH = os.environ['repos_dir'] + '/functest/'
54 if not os.path.exists(REPO_PATH):
55 logger.error("Functest repository directory not found '%s'" % REPO_PATH)
58 with open(os.environ["CONFIG_FUNCTEST_YAML"]) as f:
59 functest_yaml = yaml.safe_load(f)
62 HOME = os.environ['HOME'] + "/"
65 VM_DELETE_TIMEOUT = 100
66 PING_TIMEOUT = functest_yaml.get("vping").get("ping_timeout")
67 TEST_DB = functest_yaml.get("results").get("test_db_url")
68 NAME_VM_1 = functest_yaml.get("vping").get("vm_name_1")
69 NAME_VM_2 = functest_yaml.get("vping").get("vm_name_2")
70 GLANCE_IMAGE_NAME = functest_yaml.get("vping").get("image_name")
71 GLANCE_IMAGE_FILENAME = functest_yaml.get("general").get("openstack").get(
73 GLANCE_IMAGE_FORMAT = functest_yaml.get("general").get("openstack").get(
75 GLANCE_IMAGE_PATH = functest_yaml.get("general").get("directories").get(
76 "dir_functest_data") + "/" + GLANCE_IMAGE_FILENAME
78 FLAVOR = functest_yaml.get("vping").get("vm_flavor")
80 # NEUTRON Private Network parameters
82 PRIVATE_NET_NAME = functest_yaml.get("vping").get(
83 "vping_private_net_name")
84 PRIVATE_SUBNET_NAME = functest_yaml.get("vping").get(
85 "vping_private_subnet_name")
86 PRIVATE_SUBNET_CIDR = functest_yaml.get("vping").get(
87 "vping_private_subnet_cidr")
88 ROUTER_NAME = functest_yaml.get("vping").get(
91 SECGROUP_NAME = functest_yaml.get("vping").get("vping_sg_name")
92 SECGROUP_DESCR = functest_yaml.get("vping").get("vping_sg_descr")
101 def waitVmActive(nova, vm):
103 # sleep and wait for VM status change
105 count = VM_BOOT_TIMEOUT / sleep_time
107 status = openstack_utils.get_instance_status(nova, vm)
108 logger.debug("Status: %s" % status)
109 if status == "ACTIVE":
111 if status == "ERROR" or status == "error":
114 logger.debug("Booting a VM timed out...")
117 time.sleep(sleep_time)
121 def waitVmDeleted(nova, vm):
123 # sleep and wait for VM status change
125 count = VM_DELETE_TIMEOUT / sleep_time
127 status = openstack_utils.get_instance_status(nova, vm)
131 logger.debug("Timeout")
136 time.sleep(sleep_time)
140 def create_security_group(neutron_client):
141 sg_id = openstack_utils.get_security_group_id(neutron_client,
144 logger.info("Using existing security group '%s'..." % SECGROUP_NAME)
146 logger.info("Creating security group '%s'..." % SECGROUP_NAME)
147 SECGROUP = openstack_utils.create_security_group(neutron_client,
151 logger.error("Failed to create the security group...")
154 sg_id = SECGROUP['id']
156 logger.debug("Security group '%s' with ID=%s created successfully."
157 % (SECGROUP['name'], sg_id))
159 logger.debug("Adding ICMP rules in security group '%s'..."
161 if not openstack_utils.create_secgroup_rule(neutron_client, sg_id,
163 logger.error("Failed to create the security group rule...")
166 logger.debug("Adding SSH rules in security group '%s'..."
168 if not openstack_utils.create_secgroup_rule(
169 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
170 logger.error("Failed to create the security group rule...")
173 if not openstack_utils.create_secgroup_rule(
174 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
175 logger.error("Failed to create the security group rule...")
182 creds_nova = openstack_utils.get_credentials("nova")
183 nova_client = novaclient.Client('2', **creds_nova)
184 creds_neutron = openstack_utils.get_credentials("neutron")
185 neutron_client = neutronclient.Client(**creds_neutron)
186 creds_keystone = openstack_utils.get_credentials("keystone")
187 keystone_client = keystoneclient.Client(**creds_keystone)
188 glance_endpoint = keystone_client.service_catalog.url_for(
189 service_type='image', endpoint_type='publicURL')
190 glance_client = glanceclient.Client(1, glance_endpoint,
191 token=keystone_client.auth_token)
197 # Check if the given image exists
198 image_id = openstack_utils.get_image_id(glance_client, GLANCE_IMAGE_NAME)
200 logger.info("Using existing image '%s'..." % GLANCE_IMAGE_NAME)
204 logger.info("Creating image '%s' from '%s'..." % (GLANCE_IMAGE_NAME,
206 image_id = openstack_utils.create_glance_image(glance_client,
210 logger.error("Failed to create a Glance image...")
212 logger.debug("Image '%s' with ID=%s created successfully."
213 % (GLANCE_IMAGE_NAME, image_id))
215 network_dic = openstack_utils.create_network_full(logger,
223 "There has been a problem when creating the neutron network")
226 network_id = network_dic["net_id"]
228 sg_id = create_security_group(neutron_client)
230 # Check if the given flavor exists
232 flavor = nova_client.flavors.find(name=FLAVOR)
233 logger.info("Using existing Flavor '%s'..." % FLAVOR)
235 logger.error("Flavor '%s' not found." % FLAVOR)
236 logger.info("Available flavors are: ")
237 pMsg(nova_client.flavor.list())
240 # Deleting instances if they exist
241 servers = nova_client.servers.list()
242 for server in servers:
243 if server.name == NAME_VM_1 or server.name == NAME_VM_2:
244 logger.info("Instance %s found. Deleting..." % server.name)
248 start_time = time.time()
249 stop_time = start_time
250 logger.info("vPing Start Time:'%s'" % (
251 datetime.datetime.fromtimestamp(start_time).strftime(
252 '%Y-%m-%d %H:%M:%S')))
254 logger.info("Creating instance '%s'..." % NAME_VM_1)
256 "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
257 "network=%s \n" % (NAME_VM_1, flavor, image_id, network_id))
258 vm1 = nova_client.servers.create(
262 nics=[{"net-id": network_id}]
265 # wait until VM status is active
266 if not waitVmActive(nova_client, vm1):
267 logger.error("Instance '%s' cannot be booted. Status is '%s'" % (
268 NAME_VM_1, openstack_utils.get_instance_status(nova_client, vm1)))
271 logger.info("Instance '%s' is ACTIVE." % NAME_VM_1)
273 # Retrieve IP of first VM
274 test_ip = vm1.networks.get(PRIVATE_NET_NAME)[0]
275 logger.debug("Instance '%s' got private ip '%s'." % (NAME_VM_1, test_ip))
277 logger.info("Adding '%s' to security group '%s'..."
278 % (NAME_VM_1, SECGROUP_NAME))
279 openstack_utils.add_secgroup_to_instance(nova_client, vm1.id, sg_id)
282 logger.info("Creating instance '%s'..." % NAME_VM_2)
284 "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
285 "network=%s \n" % (NAME_VM_2, flavor, image_id, network_id))
286 vm2 = nova_client.servers.create(
290 nics=[{"net-id": network_id}]
293 if not waitVmActive(nova_client, vm2):
294 logger.error("Instance '%s' cannot be booted. Status is '%s'" % (
295 NAME_VM_2, openstack_utils.get_instance_status(nova_client, vm2)))
298 logger.info("Instance '%s' is ACTIVE." % NAME_VM_2)
300 logger.info("Adding '%s' to security group '%s'..." % (NAME_VM_2,
302 openstack_utils.add_secgroup_to_instance(nova_client, vm2.id, sg_id)
304 logger.info("Creating floating IP for VM '%s'..." % NAME_VM_2)
305 floatip_dic = openstack_utils.create_floating_ip(neutron_client)
306 floatip = floatip_dic['fip_addr']
307 # floatip_id = floatip_dic['fip_id']
310 logger.error("Cannot create floating IP.")
312 logger.info("Floating IP created: '%s'" % floatip)
314 logger.info("Associating floating ip: '%s' to VM '%s' "
315 % (floatip, NAME_VM_2))
316 if not openstack_utils.add_floating_ip(nova_client, vm2.id, floatip):
317 logger.error("Cannot associate floating IP to VM.")
320 logger.info("Trying to establish SSH connection to %s..." % floatip)
322 password = 'cubswin:)'
323 ssh = paramiko.SSHClient()
324 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
330 cidr_first_octet = PRIVATE_SUBNET_CIDR.split('.')[0]
333 ssh.connect(floatip, username=username,
334 password=password, timeout=2)
335 logger.debug("SSH connection established to %s." % floatip)
338 logger.debug("Waiting for %s..." % floatip)
342 console_log = vm2.get_console_output()
344 # print each "Sending discover" captured on the console log
345 if (len(re.findall("Sending discover", console_log)) >
346 discover_count and not got_ip):
348 logger.debug("Console-log '%s': Sending discover..."
351 # check if eth0 got an ip,the line looks like this:
352 # "inet addr:192.168."....
353 # if the dhcp agent fails to assing ip, this line will not appear
354 if "inet addr:" + cidr_first_octet in console_log and not got_ip:
356 logger.debug("The instance '%s' succeeded to get the IP "
357 "from the dhcp agent.")
359 # if dhcp doesnt work,it shows "No lease, failing".The test will fail
360 if "No lease, failing" in console_log and not nolease and not got_ip:
362 logger.debug("Console-log '%s': No lease, failing..."
364 logger.info("The instance failed to get an IP from the "
365 "DHCP agent. The test will probably timeout...")
367 if timeout == 0: # 300 sec timeout (5 min)
368 logger.error("Cannot establish connection to IP '%s'. Aborting"
372 scp = SCPClient(ssh.get_transport())
374 ping_script = REPO_PATH + "testcases/OpenStack/vPing/ping.sh"
376 scp.put(ping_script, "~/")
378 logger.error("Cannot SCP the file '%s' to VM '%s'"
379 % (ping_script, floatip))
382 cmd = 'chmod 755 ~/ping.sh'
383 (stdin, stdout, stderr) = ssh.exec_command(cmd)
384 for line in stdout.readlines():
387 logger.info("Waiting for ping...")
389 stop_time = time.time()
392 cmd = '~/ping.sh ' + test_ip
398 (stdin, stdout, stderr) = ssh.exec_command(cmd)
399 output = stdout.readlines()
402 if "vPing OK" in line:
403 logger.info("vPing detected!")
405 # we consider start time at VM1 booting
406 stop_time = time.time()
407 duration = round(stop_time - start_time, 1)
408 logger.info("vPing duration:'%s' s." % duration)
413 elif sec == PING_TIMEOUT:
414 logger.info("Timeout reached.")
419 logger.debug("Pinging %s. Waiting for response..." % test_ip)
423 logger.info("vPing OK")
426 logger.error("vPing FAILED")
430 logger.debug("Pushing vPing SSH results into DB...")
431 functest_utils.push_results_to_db("functest",
437 details={'timestart': start_time,
438 'duration': duration,
441 logger.error("Error pushing results into Database '%s'"
446 if __name__ == '__main__':