4 # Copyright 2016 RIFT.IO Inc
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # Author(s): Anil Gunturu
19 # Creation Date: 07/24/2014
23 This is a skeletal python tool that invokes the rwcal plugin
24 to perform cloud operations.
33 from gi
import require_version
34 require_version('RwCal', '1.0')
36 from gi
.repository
import GObject
, Peas
, GLib
, GIRepository
37 from gi
.repository
import RwCal
, RwTypes
39 def resource_list_subcommand(rwcloud
, cmdargs
):
40 status
, flavorinfo
= rwcloud
.get_flavor_list()
41 status
, vminfo
= rwcloud
.get_vm_list()
47 # no yaml module installed for Python3, hack for now
48 if cmdargs
.hostinfo_file_name
:
49 with
open(cmdargs
.hostinfo_file_name
, 'r') as f
:
61 hosts
[host
['name']] = host
67 host
[k
.strip()] = v
.strip()
69 # Collect the unique Top of Rack (TOR) swithes
70 tors
= set(hosts
[vm
.host_name
]['tor'].lower() for vm
in vminfo
.vminfo_list
)
73 for vm
in vminfo
.vminfo_list
:
74 _
, __
, host_ip_list
= socket
.gethostbyaddr(vm
.host_name
)
77 print(" name: {}".format(vm
.vm_name
))
78 print(" osid: {}".format(vm
.vm_id
))
79 print(" host_name: {}".format(vm
.host_name
))
80 print(" host_ip: {}".format(host_ip_list
[0]))
81 controller
, scratch
= cmdargs
.auth_url
[7:].split(':')
82 print(" controller: {}".format(controller
))
83 print(" tor: {}".format(hosts
[vm
.host_name
]['tor']))
84 print(" image_name: {}".format(vm
.image_name
))
85 print(" flavor_name: {}".format(vm
.flavor_name
))
86 print(" availability_zone: {}".format(vm
.availability_zone
))
87 print(" private_ip_list: {}".format(
88 sorted(v
.ip_address
for v
in vm
.private_ip_list
)
90 # select the 10.0 network for management ip
91 for p
in vm
.private_ip_list
:
92 if p
.ip_address
.startswith('10.0.'):
93 print(" ip_address: {}".format(p
.ip_address
))
96 print(" public_ip_list: {}".format(
97 [v
.ip_address
for v
in vm
.public_ip_list
]
99 for flavor
in flavorinfo
.flavorinfo_list
:
100 if flavor
.name
== vm
.flavor_name
:
101 print(" vcpu: {}".format(flavor
.vcpus
))
102 print(" ram: {}".format(flavor
.memory
))
103 print(" disk: {}".format(flavor
.disk
))
104 print(" host_aggregate_list: {}".format(
105 [a
.name
for a
in flavor
.host_aggregate_list
]
107 print(" pci_passthrough_device_list: {}".format(
108 [(d
.alias
,d
.count
) for d
in flavor
.pci_passthrough_device_list
]
110 # Number of openflow switches this resource connects to are the
111 # number of TOR switches for the pool for demos
112 print(" num_openflow_switches: {}".format(len(tors
)))
113 # The number of legacy switches are 0 for demos
114 print(" num_legacy_switches: 0")
115 print(" epa_attributes:")
117 # HACK: rw_wag* VMs trusted_execution is always TRUE
118 if vm
.vm_name
.startswith('rw_wag'):
119 trusted_execution
= 'TRUE'
121 trusted_execution
= str(flavor
.trusted_host_only
).upper()
122 print(" trusted_execution: {}".format(trusted_execution
))
123 print(" ddio: {}".format(hosts
[vm
.host_name
]['ddio']))
124 print(" cat: {}".format(hosts
[vm
.host_name
]['cat']))
125 print(" ovs_acceleration: {}".format(hosts
[vm
.host_name
]['ovs_acceleration']))
126 print(" mem_page_size: {}".format(flavor
.mem_page_size
))
127 if flavor
.cpu_threads
:
128 print(" cpu_threads: {}".format(flavor
.cpu_threads
))
129 print(" cpu_pinning_policy: {}".format(flavor
.cpu_policy
))
130 # print(" numa_policy: {{ node_cnt: {} }}".format(flavor.numa_node_cnt))
131 print(" numa_node_cnt: {}".format(flavor
.numa_node_cnt
))
133 # if any of the PCI passthrough devices are Coleto Creek
138 for d
in flavor
.pci_passthrough_device_list
:
139 if 'COLETO' in d
.alias
:
142 elif '10G' in d
.alias
:
144 elif '100G' in d
.alias
:
147 # NOTE: The following can break if SRIOV is used
148 # But for the demos 1,2,3 SRIOV is not used
149 # This is updated logic to set the nic to default to Niantic
150 # if 100G is not in the devise list.
154 print(" nic: NIANTIC")
156 if passthrough
or hosts
[vm
.host_name
]['ovs_acceleration'].upper() != 'DISABLED':
157 print(" dpdk_accelerated: TRUE")
159 print(" dpdk_accelerated: FALSE")
162 print(" pci_passthrough: TRUE")
164 print(" pci_passthrough: FALSE")
167 print(" quick_assist_policy: MANDATORY")
169 print(" quick_assist_policy: NOACCEL")
173 def resource_subcommand(rwcloud
, cmdargs
):
174 """Process the resources subcommand"""
176 if cmdargs
.which
== 'list':
177 resource_list_subcommand(rwcloud
, cmdargs
)
179 def vm_list_subcommand(rwcloud
, cmdargs
):
180 status
, vminfo
= rwcloud
.get_vm_list()
181 for vm
in vminfo
.vminfo_list
:
184 def vm_show_subcommand(rwcloud
, cmdargs
):
185 status
, vm
= rwcloud
.get_vm(cmdargs
.id)
188 def vm_create_subcommand(cmdargs
):
191 def vm_destroy_subcommand(cmdargs
):
194 def vm_reboot_subcommand(cmdargs
):
197 def vm_start_subcommand(cmdargs
):
200 def vm_subcommand(rwcloud
, cmdargs
):
201 """Process the vm subcommand"""
203 if cmdargs
.which
== 'list':
204 vm_list_subcommand(rwcloud
, cmdargs
)
205 elif cmdargs
.which
== 'show':
206 vm_show_subcommand(rwcloud
, cmdargs
)
207 elif cmdargs
.which
== 'create':
208 vm_create_subcommand(cmdargs
)
209 elif cmdargs
.which
== 'reboot':
210 vm_reboot_subcommand(cmdargs
)
211 elif cmdargs
.which
== 'start':
212 vm_start_subcommand(cmdargs
)
213 elif cmdargs
.which
== 'destroy':
214 vm_destroy_subcommand(cmdargs
)
216 def flavor_list_subcommand(rwcloud
, cmdargs
):
217 status
, flavorinfo
= rwcloud
.get_flavor_list()
218 for flavor
in flavorinfo
.flavorinfo_list
:
221 def flavor_show_subcommand(rwcloud
, cmdargs
):
222 status
, flavor
= rwcloud
.get_flavor(cmdargs
.id)
225 def flavor_subcommand(rwcloud
, cmdargs
):
226 """Process the flavor subcommand"""
228 if cmdargs
.which
== 'list':
229 flavor_list_subcommand(rwcloud
, cmdargs
)
230 elif cmdargs
.which
== 'show':
231 flavor_show_subcommand(rwcloud
, cmdargs
)
234 def main(args
=sys
.argv
[1:]):
235 logging
.basicConfig(format
='RWCAL %(message)s')
238 # Command line argument specification
240 desc
="""This tool is used to manage the VMs"""
241 parser
= argparse
.ArgumentParser(description
=desc
)
242 subparsers
= parser
.add_subparsers()
244 # ipaddr = socket.gethostbyname(socket.getfqdn())
245 # default_auth_url = 'http://%s:35357/v2.0/tokens' % ipaddr
246 default_auth_url
= "http://10.64.1.31:35357/v2.0/tokens"
248 parser
.add_argument('-t', '--provider-type', dest
='provider_type',
249 type=str, default
='OPENSTACK',
250 help='Cloud provider type (default: %(default)s)')
251 parser
.add_argument('-u', '--user-name', dest
='user',
252 type=str, default
='demo',
253 help='User name (default: %(default)s)')
254 parser
.add_argument('-p', '--password', dest
='passwd',
255 type=str, default
='mypasswd',
256 help='Password (default: %(default)s)')
257 parser
.add_argument('-n', '--tenant-name', dest
='tenant',
258 type=str, default
='demo',
259 help='User name (default: %(default)s)')
260 parser
.add_argument('-a', '--auth-url', dest
='auth_url',
261 type=str, default
=default_auth_url
,
262 help='Password (default: %(default)s)')
265 # Subparser for Resources
267 resource_parser
= subparsers
.add_parser('resource')
268 resource_subparsers
= resource_parser
.add_subparsers()
270 # List resource subparser
271 resource_list_parser
= resource_subparsers
.add_parser('list')
272 resource_list_parser
.set_defaults(which
='list')
273 resource_list_parser
.add_argument('-f', '--hostinfo-file-name',
274 dest
='hostinfo_file_name',
277 help='name of the static yaml file containing host information')
279 resource_parser
.set_defaults(func
=resource_subcommand
)
282 # Subparser for Flavor
284 flavor_parser
= subparsers
.add_parser('flavor')
285 flavor_subparsers
= flavor_parser
.add_subparsers()
287 # List flavor subparser
288 flavor_list_parser
= flavor_subparsers
.add_parser('list')
289 flavor_list_parser
.set_defaults(which
='list')
291 # Show flavor subparser
292 flavor_show_parser
= flavor_subparsers
.add_parser('show')
293 flavor_show_parser
.add_argument('id', type=str)
294 flavor_show_parser
.set_defaults(which
='show')
296 flavor_parser
.set_defaults(func
=flavor_subcommand
)
301 vm_parser
= subparsers
.add_parser('vm')
302 vm_subparsers
= vm_parser
.add_subparsers()
304 # Create VM subparser
305 vm_create_parser
= vm_subparsers
.add_parser('create')
306 vm_create_parser
.add_argument('-c', '--count',
308 help='The number of VMs to launch '
309 '(default: %(default)d)')
310 vm_create_parser
.add_argument('-i', '--image',
311 default
='rwopenstack_vm',
312 help='Specify the image for the VM')
313 vm_create_parser
.add_argument('-n', '--name',
314 help='Specify the name of the VM')
315 vm_create_parser
.add_argument('-f', '--flavor',
316 help='Specify the flavor for the VM')
317 vm_create_parser
.add_argument('-R', '--reserve', dest
='reserve_new_vms',
318 action
='store_true', help='reserve any newly created VMs')
319 vm_create_parser
.add_argument('-s', '--single', dest
='wait_after_create',
321 help='wait for each VM to start before creating the next')
323 vm_create_parser
.set_defaults(which
='create')
325 # Reboot VM subparser
326 vm_reboot_parser
= vm_subparsers
.add_parser('reboot')
327 group
= vm_reboot_parser
.add_mutually_exclusive_group()
328 group
.add_argument('-n', '--vm-name', dest
='vm_name',
330 help='Specify the name of the VM')
331 group
.add_argument('-a', '--reboot-all',
332 dest
='reboot_all', action
='store_true',
333 help='Reboot all VMs')
334 vm_reboot_parser
.add_argument('-s', '--sleep',
337 help='time in seconds to sleep between reboots')
338 vm_reboot_parser
.set_defaults(which
='reboot')
340 # Destroy VM subparser
341 vm_destroy_parser
= vm_subparsers
.add_parser('destroy')
342 group
= vm_destroy_parser
.add_mutually_exclusive_group()
343 group
.add_argument('-n', '--vm-name', dest
='vm_name',
345 help='Specify the name of the VM (accepts regular expressions)')
346 group
.add_argument('-a', '--destroy-all',
347 dest
='destroy_all', action
='store_true',
348 help='Delete all VMs')
349 group
.add_argument('-w', '--wait',
350 dest
='wait', action
='store_true',
351 help='destroy all and wait until all VMs have exited')
352 vm_destroy_parser
.set_defaults(which
='destroy')
355 vm_list_parser
= vm_subparsers
.add_parser('list')
356 vm_list_parser
.set_defaults(which
='list')
357 vm_list_parser
.add_argument('-i', '--ips_only', dest
='ipsonly',
359 help='only list IP addresses')
362 vm_show_parser
= vm_subparsers
.add_parser('show')
363 vm_show_parser
.add_argument('id', type=str)
364 vm_show_parser
.set_defaults(which
='show')
365 vm_parser
.set_defaults(func
=vm_subcommand
)
367 cmdargs
= parser
.parse_args(args
)
369 # Open the peas engine
370 engine
= Peas
.Engine
.get_default()
372 # Load our plugin proxy into the g_irepository namespace
373 default
= GIRepository
.Repository
.get_default()
374 GIRepository
.Repository
.require(default
, "RwCal", "1.0", 0)
376 # Enable python language loader
377 engine
.enable_loader("python3");
379 # Set the search path for peas engine,
380 # rift-shell sets the PLUGINDIR and GI_TYPELIB_PATH
382 paths
= paths
.union(os
.environ
['PLUGINDIR'].split(":"))
384 engine
.add_search_path(path
, path
)
386 # Load the rwcal python plugin and create the extension.
387 info
= engine
.get_plugin_info("rwcal-plugin")
389 print("Error loading rwcal-python plugin")
391 engine
.load_plugin(info
)
392 rwcloud
= engine
.create_extension(info
, RwCal
.Cloud
, None)
394 # For now cloud credentials are hard coded
395 if cmdargs
.provider_type
== 'OPENSTACK':
396 provider_type
= RwCal
.CloudType
.OPENSTACK_AUTH_URL
397 elif cmdargs
.provider_type
== 'EC2_US_EAST':
398 provider_type
= RwCal
.CloudType
.EC2_US_EAST
399 elif cmdargs
.provider_type
== 'VSPHERE':
400 provider_type
= RwCal
.CloudType
.VSPHERE
402 sys
.exit("Cloud provider %s is NOT supported yet" % cmdargs
.provider_type
)
405 if not 'RIFT_SHELL' in os
.environ
:
406 sys
.stderr
.write("This tool should be run from inside a rift-shell")
408 status
= rwcloud
.init(provider_type
,
414 assert status
== RwTypes
.RwStatus
.SUCCESS
416 cmdargs
.func(rwcloud
, cmdargs
)
418 if __name__
== "__main__":