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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
13 # Note: this is script works only with Ubuntu image, not with Cirros image
22 import novaclient.v2.client as novaclient
23 #import novaclient.v1_1.client as novaclient
24 import cinderclient.v1.client as cinderclient
25 pp = pprint.PrettyPrinter(indent=4)
29 #tODO: this parameters should be taken from a conf file
31 NAME_VM_1 = "opnfv-vping-1"
32 NAME_VM_2 = "opnfv-vping-2"
33 GLANCE_IMAGE_NAME = "trusty-server-cloudimg-amd64-disk1.img"
34 NEUTRON_NET_NAME = "test"
37 parser = argparse.ArgumentParser()
38 parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
39 args = parser.parse_args()
41 """ logging configuration """
42 logger = logging.getLogger('vPing')
43 logger.setLevel(logging.DEBUG)
45 ch = logging.StreamHandler()
47 ch.setLevel(logging.DEBUG)
49 ch.setLevel(logging.INFO)
50 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
51 ch.setFormatter(formatter)
60 def print_title(title):
62 print "\n"+"#"*40+"\n# "+title+"\n"+"#"*40+"\n"
64 def get_credentials(service):
65 """Returns a creds dictionary filled with the following keys:
67 * password/api_key (depending on the service)
68 * tenant_name/project_id (depending on the service)
70 :param service: a string indicating the name of the service
71 requesting the credentials.
73 #TODO: get credentials from the openrc file
75 # Unfortunately, each of the OpenStack client will request slightly
76 # different entries in their credentials dict.
77 if service.lower() in ("nova", "cinder"):
82 tenant = "tenant_name"
84 # The most common way to pass these info to the script is to do it through
85 # environment variables.
87 "username": os.environ.get('OS_USERNAME', "admin"), # add your cloud username details
88 password: os.environ.get("OS_PASSWORD", 'admin'), # add password
89 "auth_url": os.environ.get("OS_AUTH_URL","http://192.168.20.71:5000/v2.0"), # Auth URL
90 tenant: os.environ.get("OS_TENANT_NAME", "admin"),
96 def get_server(creds, servername):
97 nova = novaclient.Client(**creds)
98 return nova.servers.find(name=servername)
101 def waitVmActive(nova,vm):
102 # sleep and wait for VM status change
103 while get_status(nova,vm) != "ACTIVE":
105 logger.debug("Status: %s" % vm.status)
106 logger.debug("Status: %s" % vm.status)
108 def get_status(nova,vm):
109 vm = nova.servers.get(vm.id)
114 creds = get_credentials("nova")
115 nova = novaclient.Client(**creds)
116 cinder = cinderclient.Client(**creds)
119 # print images and server resources
121 print_title("images list")
122 pMsg(nova.images.list())
123 print_title("servers list")
124 pMsg(nova.servers.list())
127 images=nova.images.list()
130 if image.name == GLANCE_IMAGE_NAME:
131 logger.info("Glance image found '%s'" %image.name)
134 logger.error("ERROR: Glance image %s not found." % GLANCE_IMAGE_NAME)
135 logger.info("Available images are: ")
136 pMsg(nova.images.list())
139 servers=nova.servers.list()
140 for server in servers:
141 if server.name == NAME_VM_1 or server.name == NAME_VM_2:
142 logger.info("Instance %s found. Deleting..." %server.name)
149 # tune (e.g. flavor, images, network) to your specific openstack configuration here
151 f = nova.flavors.find(name = FLAVOR)
152 i = nova.images.find(name = GLANCE_IMAGE_NAME)
153 n = nova.networks.find(label = NEUTRON_NET_NAME)
154 u = "#cloud-config\npassword: opnfv\nchpasswd: { expire: False }\nssh_pwauth: True"
158 logger.info("Creating instance '%s'..." %m)
159 logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(m,f,i,n,u))
160 vm1 = nova.servers.create(
164 nics = [{"net-id": n.id}],
172 #wait until VM status is active
173 waitVmActive(nova,vm1)
175 #retrieve IP of first VM
176 logger.debug("Fetching IP...")
177 server = get_server(creds, m)
178 #pMsg(server.networks)
179 # theoretically there is only one IP address so we take the first element of the table
180 # Dangerous! To be improved!
181 test_ip = server.networks.get(NEUTRON_NET_NAME)[0]
182 logger.debug("Instance '%s' got %s" %(m,test_ip))
183 test_cmd = '/tmp/vping.sh %s'%test_ip
187 # we will boot then execute a ping script with cloud-init
188 # the long chain corresponds to the ping procedure converted with base 64
189 # tune (e.g. flavor, images, network) to your specific openstack configuration here
191 f = nova.flavors.find(name = FLAVOR)
192 i = nova.images.find(name = GLANCE_IMAGE_NAME)
193 n = nova.networks.find(label = NEUTRON_NET_NAME)
194 # use base 64 format becaus bad surprises with sh script with cloud-init but script is just pinging
196 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
198 logger.info("Creating instance '%s'..." %m)
199 logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(m,f,i,n,u))
200 vm2 = nova.servers.create(
204 nics = [{"net-id": n.id}],
207 #security_groups = s,
210 # The injected script will shutdown the VM2 when the ping works
211 # The console-log method is more consistent but doesn't work yet
213 waitVmActive(nova,vm2)
215 logger.info("Waiting for ping, timeout is %d sec..." % PING_TIMEOUT)
218 status = get_status(nova, vm2)
220 if status == "SHUTOFF" :
222 logger.info("vPing SUCCESSFUL after %d sec" % sec)
224 if sec == PING_TIMEOUT:
225 logger.info("Timeout. vPing UNSUCCESSFUL.")
231 # I leave this here until we fix the console-log output
233 console_log = vm2.get_console_output()
234 while not ("vPing" in console_log):
236 console_log = vm2.get_console_output()
237 print "--"+console_log
239 # report if the test is failed
240 if "vPing" in console_log:
244 pMsg("no vPing detected....")
246 if sec == PING_TIMEOUT:
251 logger.debug("Deleting Instances...")
252 nova.servers.delete(vm1)
253 logger.debug("Instance %s terminated." % NAME_VM_1)
254 nova.servers.delete(vm2)
255 logger.debug("Instance %s terminated." % NAME_VM_2)
258 logger.debug("EXIT_CODE=%s" % EXIT_CODE)
262 if __name__ == '__main__':