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
24 from scp import SCPClient
26 from novaclient import client as novaclient
27 from neutronclient.v2_0 import client as neutronclient
28 from keystoneclient.v2_0 import client as keystoneclient
29 from glanceclient import client as glanceclient
31 import functest.utils.functest_logger as ft_logger
32 import functest.utils.functest_utils as functest_utils
33 import functest.utils.openstack_utils as openstack_utils
35 pp = pprint.PrettyPrinter(indent=4)
37 parser = argparse.ArgumentParser()
40 parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
41 parser.add_argument("-r", "--report",
42 help="Create json result file",
45 args = parser.parse_args()
47 """ logging configuration """
48 logger = ft_logger.Logger("vping_ssh").getLogger()
50 paramiko.util.log_to_file("/var/log/paramiko.log")
52 REPO_PATH = os.environ['repos_dir'] + '/functest/'
53 if not os.path.exists(REPO_PATH):
54 logger.error("Functest repository directory not found '%s'" % REPO_PATH)
57 with open(os.environ["CONFIG_FUNCTEST_YAML"]) as f:
58 functest_yaml = yaml.safe_load(f)
61 HOME = os.environ['HOME'] + "/"
64 VM_DELETE_TIMEOUT = 100
65 PING_TIMEOUT = functest_yaml.get("vping").get("ping_timeout")
66 TEST_DB = functest_yaml.get("results").get("test_db_url")
67 NAME_VM_1 = functest_yaml.get("vping").get("vm_name_1")
68 NAME_VM_2 = functest_yaml.get("vping").get("vm_name_2")
69 GLANCE_IMAGE_NAME = functest_yaml.get("vping").get("image_name")
70 GLANCE_IMAGE_FILENAME = functest_yaml.get("general").get("openstack").get(
72 GLANCE_IMAGE_FORMAT = functest_yaml.get("general").get("openstack").get(
74 GLANCE_IMAGE_PATH = functest_yaml.get("general").get("directories").get(
75 "dir_functest_data") + "/" + GLANCE_IMAGE_FILENAME
77 FLAVOR = functest_yaml.get("vping").get("vm_flavor")
79 # NEUTRON Private Network parameters
81 PRIVATE_NET_NAME = functest_yaml.get("vping").get(
82 "vping_private_net_name")
83 PRIVATE_SUBNET_NAME = functest_yaml.get("vping").get(
84 "vping_private_subnet_name")
85 PRIVATE_SUBNET_CIDR = functest_yaml.get("vping").get(
86 "vping_private_subnet_cidr")
87 ROUTER_NAME = functest_yaml.get("vping").get(
90 SECGROUP_NAME = functest_yaml.get("vping").get("vping_sg_name")
91 SECGROUP_DESCR = functest_yaml.get("vping").get("vping_sg_descr")
100 def waitVmActive(nova, vm):
102 # sleep and wait for VM status change
104 count = VM_BOOT_TIMEOUT / sleep_time
106 status = openstack_utils.get_instance_status(nova, vm)
107 logger.debug("Status: %s" % status)
108 if status == "ACTIVE":
110 if status == "ERROR" or status == "error":
113 logger.debug("Booting a VM timed out...")
116 time.sleep(sleep_time)
120 def waitVmDeleted(nova, vm):
122 # sleep and wait for VM status change
124 count = VM_DELETE_TIMEOUT / sleep_time
126 status = openstack_utils.get_instance_status(nova, vm)
130 logger.debug("Timeout")
135 time.sleep(sleep_time)
139 def create_security_group(neutron_client):
140 sg_id = openstack_utils.get_security_group_id(neutron_client,
143 logger.info("Using existing security group '%s'..." % SECGROUP_NAME)
145 logger.info("Creating security group '%s'..." % SECGROUP_NAME)
146 SECGROUP = openstack_utils.create_security_group(neutron_client,
150 logger.error("Failed to create the security group...")
153 sg_id = SECGROUP['id']
155 logger.debug("Security group '%s' with ID=%s created successfully."
156 % (SECGROUP['name'], sg_id))
158 logger.debug("Adding ICMP rules in security group '%s'..."
160 if not openstack_utils.create_secgroup_rule(neutron_client, sg_id,
162 logger.error("Failed to create the security group rule...")
165 logger.debug("Adding SSH rules in security group '%s'..."
167 if not openstack_utils.create_secgroup_rule(
168 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
169 logger.error("Failed to create the security group rule...")
172 if not openstack_utils.create_secgroup_rule(
173 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
174 logger.error("Failed to create the security group rule...")
179 def push_results(start_time_ts, duration, test_status):
181 logger.debug("Pushing result into DB...")
182 scenario = functest_utils.get_scenario(logger)
183 version = functest_utils.get_version(logger)
185 if test_status == "OK":
187 pod_name = functest_utils.get_pod_name(logger)
188 build_tag = functest_utils.get_build_tag(logger)
189 functest_utils.push_results_to_db(TEST_DB,
192 logger, pod_name, version, scenario,
194 payload={'timestart': start_time_ts,
195 'duration': duration,
196 'status': test_status})
198 logger.error("Error pushing results into Database '%s'"
204 creds_nova = openstack_utils.get_credentials("nova")
205 nova_client = novaclient.Client('2', **creds_nova)
206 creds_neutron = openstack_utils.get_credentials("neutron")
207 neutron_client = neutronclient.Client(**creds_neutron)
208 creds_keystone = openstack_utils.get_credentials("keystone")
209 keystone_client = keystoneclient.Client(**creds_keystone)
210 glance_endpoint = keystone_client.service_catalog.url_for(
211 service_type='image', endpoint_type='publicURL')
212 glance_client = glanceclient.Client(1, glance_endpoint,
213 token=keystone_client.auth_token)
219 # Check if the given image exists
220 image_id = openstack_utils.get_image_id(glance_client, GLANCE_IMAGE_NAME)
222 logger.info("Using existing image '%s'..." % GLANCE_IMAGE_NAME)
226 logger.info("Creating image '%s' from '%s'..." % (GLANCE_IMAGE_NAME,
228 image_id = openstack_utils.create_glance_image(glance_client,
232 logger.error("Failed to create a Glance image...")
234 logger.debug("Image '%s' with ID=%s created successfully."
235 % (GLANCE_IMAGE_NAME, image_id))
237 network_dic = openstack_utils.create_network_full(logger,
245 "There has been a problem when creating the neutron network")
248 network_id = network_dic["net_id"]
250 sg_id = create_security_group(neutron_client)
252 # Check if the given flavor exists
254 flavor = nova_client.flavors.find(name=FLAVOR)
255 logger.info("Using existing Flavor '%s'..." % FLAVOR)
257 logger.error("Flavor '%s' not found." % FLAVOR)
258 logger.info("Available flavors are: ")
259 pMsg(nova_client.flavor.list())
262 # Deleting instances if they exist
263 servers = nova_client.servers.list()
264 for server in servers:
265 if server.name == NAME_VM_1 or server.name == NAME_VM_2:
266 logger.info("Instance %s found. Deleting..." % server.name)
270 start_time_ts = time.time()
271 end_time_ts = start_time_ts
272 logger.info("vPing Start Time:'%s'" % (
273 datetime.datetime.fromtimestamp(start_time_ts).strftime(
274 '%Y-%m-%d %H:%M:%S')))
276 logger.info("Creating instance '%s'..." % NAME_VM_1)
278 "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
279 "network=%s \n" % (NAME_VM_1, flavor, image_id, network_id))
280 vm1 = nova_client.servers.create(
284 nics=[{"net-id": network_id}]
287 # wait until VM status is active
288 if not waitVmActive(nova_client, vm1):
289 logger.error("Instance '%s' cannot be booted. Status is '%s'" % (
290 NAME_VM_1, openstack_utils.get_instance_status(nova_client, vm1)))
293 logger.info("Instance '%s' is ACTIVE." % NAME_VM_1)
295 # Retrieve IP of first VM
296 test_ip = vm1.networks.get(PRIVATE_NET_NAME)[0]
297 logger.debug("Instance '%s' got private ip '%s'." % (NAME_VM_1, test_ip))
299 logger.info("Adding '%s' to security group '%s'..."
300 % (NAME_VM_1, SECGROUP_NAME))
301 openstack_utils.add_secgroup_to_instance(nova_client, vm1.id, sg_id)
304 logger.info("Creating instance '%s'..." % NAME_VM_2)
306 "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
307 "network=%s \n" % (NAME_VM_2, flavor, image_id, network_id))
308 vm2 = nova_client.servers.create(
312 nics=[{"net-id": network_id}]
315 if not waitVmActive(nova_client, vm2):
316 logger.error("Instance '%s' cannot be booted. Status is '%s'" % (
317 NAME_VM_2, openstack_utils.get_instance_status(nova_client, vm2)))
320 logger.info("Instance '%s' is ACTIVE." % NAME_VM_2)
322 logger.info("Adding '%s' to security group '%s'..." % (NAME_VM_2,
324 openstack_utils.add_secgroup_to_instance(nova_client, vm2.id, sg_id)
326 logger.info("Creating floating IP for VM '%s'..." % NAME_VM_2)
327 floatip_dic = openstack_utils.create_floating_ip(neutron_client)
328 floatip = floatip_dic['fip_addr']
329 # floatip_id = floatip_dic['fip_id']
332 logger.error("Cannot create floating IP.")
334 logger.info("Floating IP created: '%s'" % floatip)
336 logger.info("Associating floating ip: '%s' to VM '%s' "
337 % (floatip, NAME_VM_2))
338 if not openstack_utils.add_floating_ip(nova_client, vm2.id, floatip):
339 logger.error("Cannot associate floating IP to VM.")
342 logger.info("Trying to establish SSH connection to %s..." % floatip)
344 password = 'cubswin:)'
345 ssh = paramiko.SSHClient()
346 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
352 cidr_first_octet = PRIVATE_SUBNET_CIDR.split('.')[0]
355 ssh.connect(floatip, username=username,
356 password=password, timeout=2)
357 logger.debug("SSH connection established to %s." % floatip)
360 logger.debug("Waiting for %s..." % floatip)
364 console_log = vm2.get_console_output()
366 # print each "Sending discover" captured on the console log
367 if (len(re.findall("Sending discover", console_log)) >
368 discover_count and not got_ip):
370 logger.debug("Console-log '%s': Sending discover..."
373 # check if eth0 got an ip,the line looks like this:
374 # "inet addr:192.168."....
375 # if the dhcp agent fails to assing ip, this line will not appear
376 if "inet addr:" + cidr_first_octet in console_log and not got_ip:
378 logger.debug("The instance '%s' succeeded to get the IP "
379 "from the dhcp agent.")
381 # if dhcp doesnt work,it shows "No lease, failing".The test will fail
382 if "No lease, failing" in console_log and not nolease and not got_ip:
384 logger.debug("Console-log '%s': No lease, failing..."
386 logger.info("The instance failed to get an IP from the "
387 "DHCP agent. The test will probably timeout...")
389 if timeout == 0: # 300 sec timeout (5 min)
390 logger.error("Cannot establish connection to IP '%s'. Aborting"
394 scp = SCPClient(ssh.get_transport())
396 ping_script = REPO_PATH + "testcases/OpenStack/vPing/ping.sh"
398 scp.put(ping_script, "~/")
400 logger.error("Cannot SCP the file '%s' to VM '%s'"
401 % (ping_script, floatip))
404 cmd = 'chmod 755 ~/ping.sh'
405 (stdin, stdout, stderr) = ssh.exec_command(cmd)
406 for line in stdout.readlines():
409 logger.info("Waiting for ping...")
413 cmd = '~/ping.sh ' + test_ip
417 (stdin, stdout, stderr) = ssh.exec_command(cmd)
418 output = stdout.readlines()
421 if "vPing OK" in line:
422 logger.info("vPing detected!")
424 # we consider start time at VM1 booting
425 end_time_ts = time.time()
426 duration = round(end_time_ts - start_time_ts, 1)
427 logger.info("vPing duration:'%s' s." % duration)
432 elif sec == PING_TIMEOUT:
433 logger.info("Timeout reached.")
438 logger.debug("Pinging %s. Waiting for response..." % test_ip)
443 logger.info("vPing OK")
447 logger.error("vPing FAILED")
450 push_results(start_time_ts, duration, test_status)
454 if __name__ == '__main__':