Merge "Addressed review comments for https://osm.etsi.org/gerrit/#/c/2068/"
[osm/osmclient.git] / osmclient / scripts / osm.py
1 # Copyright 2017 Sandvine
2 #
3 # All Rights Reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16 """
17 OSM shell/cli
18 """
19
20 import click
21 from osmclient.client import client
22 from osmclient.common.exceptions import ClientException
23 from prettytable import PrettyTable
24 import json
25 import time
26
27
28 @click.group()
29 @click.option('--hostname',
30 default=None,
31 envvar='OSM_HOSTNAME',
32 help='hostname of server. ' +
33 'Also can set OSM_HOSTNAME in environment')
34 @click.option('--so-port',
35 default=8008,
36 envvar='OSM_SO_PORT',
37 help='hostname of server. ' +
38 'Also can set OSM_SO_PORT in environment')
39 @click.option('--ro-hostname',
40 default=None,
41 envvar='OSM_RO_HOSTNAME',
42 help='hostname of RO server. ' +
43 'Also can set OSM_RO_HOSTNAME in environment')
44 @click.option('--ro-port',
45 default=9090,
46 envvar='OSM_RO_PORT',
47 help='hostname of RO server. ' +
48 'Also can set OSM_RO_PORT in environment')
49 @click.pass_context
50 def cli(ctx, hostname, so_port, ro_hostname, ro_port):
51 if hostname is None:
52 print(
53 "either hostname option or OSM_HOSTNAME " +
54 "environment variable needs to be specified")
55 exit(1)
56 ctx.obj = client.Client(
57 host=hostname,
58 so_port=so_port,
59 ro_host=ro_hostname,
60 ro_port=ro_port)
61
62
63 @cli.command(name='ns-list')
64 @click.pass_context
65 def ns_list(ctx):
66 resp = ctx.obj.ns.list()
67 table = PrettyTable(
68 ['ns instance name',
69 'id',
70 'operational status',
71 'config status'])
72 for ns in resp:
73 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
74 nsr = nsopdata['nsr:nsr']
75 table.add_row(
76 [nsr['name-ref'],
77 nsr['ns-instance-config-ref'],
78 nsr['operational-status'],
79 nsr['config-status']])
80 table.align = 'l'
81 print(table)
82
83
84 @cli.command(name='nsd-list')
85 @click.pass_context
86 def nsd_list(ctx):
87 resp = ctx.obj.nsd.list()
88 table = PrettyTable(['nsd name', 'id'])
89 for ns in resp:
90 table.add_row([ns['name'], ns['id']])
91 table.align = 'l'
92 print(table)
93
94
95 @cli.command(name='vnfd-list')
96 @click.pass_context
97 def vnfd_list(ctx):
98 resp = ctx.obj.vnfd.list()
99 table = PrettyTable(['vnfd name', 'id'])
100 for vnfd in resp:
101 table.add_row([vnfd['name'], vnfd['id']])
102 table.align = 'l'
103 print(table)
104
105
106 @cli.command(name='vnf-list')
107 @click.pass_context
108 def vnf_list(ctx):
109 resp = ctx.obj.vnf.list()
110 table = PrettyTable(
111 ['vnf name',
112 'id',
113 'operational status',
114 'config status'])
115 for vnfr in resp:
116 if 'mgmt-interface' not in vnfr:
117 vnfr['mgmt-interface'] = {}
118 vnfr['mgmt-interface']['ip-address'] = None
119 table.add_row(
120 [vnfr['name'],
121 vnfr['id'],
122 vnfr['operational-status'],
123 vnfr['config-status']])
124 table.align = 'l'
125 print(table)
126
127
128 @cli.command(name='vnf-show')
129 @click.argument('vnf_name')
130 @click.option('--filter', default=None)
131 @click.pass_context
132 def vnf_show(ctx, vnf_name, filter):
133 try:
134 resp = ctx.obj.vnf.get(vnf_name)
135 except ClientException as inst:
136 print(inst.message)
137 exit(1)
138
139 table = PrettyTable(['field', 'value'])
140 for k, v in resp.items():
141 if filter is None or filter in k:
142 table.add_row([k, json.dumps(v, indent=2)])
143 table.align = 'l'
144 print(table)
145
146
147 @cli.command(name='vnf-monitoring-show')
148 @click.argument('vnf_name')
149 @click.pass_context
150 def vnf_monitoring_show(ctx, vnf_name):
151 try:
152 resp = ctx.obj.vnf.get_monitoring(vnf_name)
153 except ClientException as inst:
154 print(inst.message)
155 exit(1)
156
157 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
158 if resp is not None:
159 for monitor in resp:
160 table.add_row(
161 [vnf_name,
162 monitor['name'],
163 monitor['value-integer'],
164 monitor['units']])
165 table.align = 'l'
166 print(table)
167
168
169 @cli.command(name='ns-monitoring-show')
170 @click.argument('ns_name')
171 @click.pass_context
172 def ns_monitoring_show(ctx, ns_name):
173 try:
174 resp = ctx.obj.ns.get_monitoring(ns_name)
175 except ClientException as inst:
176 print(inst.message)
177 exit(1)
178
179 table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
180 for key, val in resp.items():
181 for monitor in val:
182 table.add_row(
183 [key,
184 monitor['name'],
185 monitor['value-integer'],
186 monitor['units']])
187 table.align = 'l'
188 print(table)
189
190
191 @cli.command(name='ns-create')
192 @click.option('--ns_name',
193 prompt=True)
194 @click.option('--nsd_name',
195 prompt=True)
196 @click.option('--vim_account',
197 prompt=True)
198 @click.option('--admin_status',
199 default='ENABLED',
200 help='administration status')
201 @click.option('--ssh_keys',
202 default=None,
203 help='comma separated list of keys to inject to vnfs')
204 @click.option('--vim_network_prefix',
205 default=None,
206 help='vim network name prefix')
207 @click.pass_context
208 def ns_create(ctx,
209 nsd_name,
210 ns_name,
211 vim_account,
212 admin_status,
213 ssh_keys,
214 vim_network_prefix):
215 try:
216 ctx.obj.ns.create(
217 nsd_name,
218 ns_name,
219 vim_network_prefix=vim_network_prefix,
220 ssh_keys=ssh_keys,
221 account=vim_account)
222 except ClientException as inst:
223 print(inst.message)
224 exit(1)
225
226
227 @cli.command(name='ns-delete')
228 @click.argument('ns_name')
229 @click.pass_context
230 def ns_delete(ctx, ns_name):
231 try:
232 ctx.obj.ns.delete(ns_name)
233 except ClientException as inst:
234 print(inst.message)
235 exit(1)
236
237
238 @cli.command(name='upload-package')
239 @click.argument('filename')
240 @click.pass_context
241 def upload_package(ctx, filename):
242 try:
243 ctx.obj.package.upload(filename)
244 ctx.obj.package.wait_for_upload(filename)
245 except ClientException as inst:
246 print(inst.message)
247 exit(1)
248
249
250 @cli.command(name='ns-show')
251 @click.argument('ns_name')
252 @click.option('--filter', default=None)
253 @click.pass_context
254 def ns_show(ctx, ns_name, filter):
255 try:
256 ns = ctx.obj.ns.get(ns_name)
257 except ClientException as inst:
258 print(inst.message)
259 exit(1)
260
261 table = PrettyTable(['field', 'value'])
262
263 for k, v in ns.items():
264 if filter is None or filter in k:
265 table.add_row([k, json.dumps(v, indent=2)])
266
267 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
268 nsr_optdata = nsopdata['nsr:nsr']
269 for k, v in nsr_optdata.items():
270 if filter is None or filter in k:
271 table.add_row([k, json.dumps(v, indent=2)])
272 table.align = 'l'
273 print(table)
274
275
276 @cli.command(name='ns-scaling-show')
277 @click.argument('ns_name')
278 @click.pass_context
279 def show_ns_scaling(ctx, ns_name):
280 resp = ctx.obj.ns.list()
281
282 table = PrettyTable(
283 ['group-name',
284 'instance-id',
285 'operational status',
286 'create-time',
287 'vnfr ids'])
288
289 for ns in resp:
290 if ns_name == ns['name']:
291 nsopdata = ctx.obj.ns.get_opdata(ns['id'])
292 scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
293 for record in scaling_records:
294 if 'instance' in record:
295 instances = record['instance']
296 for inst in instances:
297 table.add_row(
298 [record['scaling-group-name-ref'],
299 inst['instance-id'],
300 inst['op-status'],
301 time.strftime('%Y-%m-%d %H:%M:%S',
302 time.localtime(
303 inst['create-time'])),
304 inst['vnfrs']])
305 table.align = 'l'
306 print(table)
307
308
309 @cli.command(name='ns-scale')
310 @click.argument('ns_name')
311 @click.option('--ns_scale_group', prompt=True)
312 @click.option('--index', prompt=True)
313 @click.pass_context
314 def ns_scale(ctx, ns_name, ns_scale_group, index):
315 ctx.obj.ns.scale(ns_name, ns_scale_group, index)
316
317
318 @cli.command(name='nsd-delete')
319 @click.argument('nsd_name')
320 @click.pass_context
321 def nsd_delete(ctx, nsd_name):
322 try:
323 ctx.obj.nsd.delete(nsd_name)
324 except ClientException as inst:
325 print(inst.message)
326 exit(1)
327
328
329 @cli.command(name='vnfd-delete')
330 @click.argument('vnfd_name')
331 @click.pass_context
332 def vnfd_delete(ctx, vnfd_name):
333 try:
334 ctx.obj.vnfd.delete(vnfd_name)
335 except ClientException as inst:
336 print(inst.message)
337 exit(1)
338
339
340 @cli.command(name='config-agent-list')
341 @click.pass_context
342 def config_agent_list(ctx):
343 table = PrettyTable(['name', 'account-type', 'details'])
344 for account in ctx.obj.vca.list():
345 table.add_row(
346 [account['name'],
347 account['account-type'],
348 account['juju']])
349 table.align = 'l'
350 print(table)
351
352
353 @cli.command(name='config-agent-delete')
354 @click.argument('name')
355 @click.pass_context
356 def config_agent_delete(ctx, name):
357 try:
358 ctx.obj.vca.delete(name)
359 except ClientException as inst:
360 print(inst.message)
361 exit(1)
362
363
364 @cli.command(name='config-agent-add')
365 @click.option('--name',
366 prompt=True)
367 @click.option('--account_type',
368 prompt=True)
369 @click.option('--server',
370 prompt=True)
371 @click.option('--user',
372 prompt=True)
373 @click.option('--secret',
374 prompt=True,
375 hide_input=True,
376 confirmation_prompt=True)
377 @click.pass_context
378 def config_agent_add(ctx, name, account_type, server, user, secret):
379 try:
380 ctx.obj.vca.create(name, account_type, server, user, secret)
381 except ClientException as inst:
382 print(inst.message)
383 exit(1)
384
385
386 @cli.command(name='vim-create')
387 @click.option('--name',
388 prompt=True,
389 help='Name to create datacenter')
390 @click.option('--user',
391 prompt=True,
392 help='VIM username')
393 @click.option('--password',
394 prompt=True,
395 hide_input=True,
396 confirmation_prompt=True,
397 help='VIM password')
398 @click.option('--auth_url',
399 prompt=True,
400 help='VIM connector url')
401 @click.option('--tenant',
402 prompt=True,
403 help='tenant name')
404 @click.option('--floating_ip_pool',
405 default=None)
406 @click.option('--keypair',
407 default=None)
408 @click.option('--config',
409 default=None,
410 help='VIM specific config parameters')
411 @click.option('--account_type',
412 default='openstack',
413 help='VIM type')
414 @click.option('--description',
415 default='no description')
416 @click.pass_context
417 def vim_create(ctx,
418 name,
419 user,
420 password,
421 auth_url,
422 tenant,
423 floating_ip_pool,
424 keypair,
425 config,
426 account_type,
427 description):
428 vim = {}
429 vim['vim-username'] = user
430 vim['vim-password'] = password
431 vim['vim-url'] = auth_url
432 vim['vim-tenant-name'] = tenant
433 vim['floating_ip_pool'] = floating_ip_pool
434 vim['keypair'] = keypair
435 vim['config'] = config
436 vim['vim-type'] = account_type
437 vim['description'] = description
438 try:
439 ctx.obj.vim.create(name, vim)
440 except ClientException as inst:
441 print(inst.message)
442 exit(1)
443
444
445 @cli.command(name='vim-delete')
446 @click.argument('name')
447 @click.pass_context
448 def vim_delete(ctx, name):
449 try:
450 ctx.obj.vim.delete(name)
451 except ClientException as inst:
452 print(inst.message)
453 exit(1)
454
455
456 @cli.command(name='vim-list')
457 @click.pass_context
458 def vim_list(ctx):
459 resp = ctx.obj.vim.list()
460 table = PrettyTable(['vim name', 'uuid'])
461 for vim in resp:
462 table.add_row([vim['name'], vim['uuid']])
463 table.align = 'l'
464 print(table)
465
466
467 @cli.command(name='vim-show')
468 @click.argument('name')
469 @click.pass_context
470 def vim_show(ctx, name):
471 try:
472 resp = ctx.obj.vim.get(name)
473 except ClientException as inst:
474 print(inst.message)
475 exit(1)
476
477 table = PrettyTable(['key', 'attribute'])
478 for k, v in resp.items():
479 table.add_row([k, json.dumps(v, indent=2)])
480 table.align = 'l'
481 print(table)
482
483
484 @cli.command(name='ro-dump')
485 @click.pass_context
486 def ro_dump(ctx):
487 resp = ctx.obj.vim.get_resource_orchestrator()
488 table = PrettyTable(['key', 'attribute'])
489 for k, v in resp.items():
490 table.add_row([k, json.dumps(v, indent=2)])
491 table.align = 'l'
492 print(table)
493
494
495 @cli.command(name='vcs-list')
496 @click.pass_context
497 def vcs_list(ctx):
498 resp = ctx.obj.utils.get_vcs_info()
499 table = PrettyTable(['component name', 'state'])
500 for component in resp:
501 table.add_row([component['component_name'], component['state']])
502 table.align = 'l'
503 print(table)
504
505
506 if __name__ == '__main__':
507 cli()