Code Coverage

Cobertura Coverage Report > osmclient.scripts >

osm.py

Trend

Classes0%
 
Lines0%
 
Conditionals100%
 

File Coverage summary

NameClassesLinesConditionals
osm.py
0%
0/1
0%
0/2002
100%
0/0

Coverage Breakdown by Class

NameLinesConditionals
osm.py
0%
0/2002
N/A

Source

osmclient/scripts/osm.py
1 # Copyright 2017-2018 Sandvine
2 # Copyright 2018 Telefonica
3 #
4 # All Rights Reserved.
5 #
6 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
7 #    not use this file except in compliance with the License. You may obtain
8 #    a copy of the License at
9 #
10 #         http://www.apache.org/licenses/LICENSE-2.0
11 #
12 #    Unless required by applicable law or agreed to in writing, software
13 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 #    License for the specific language governing permissions and limitations
16 #    under the License.
17 0 """
18 OSM shell/cli
19 """
20
21 0 import click
22 0 from osmclient import client
23 0 from osmclient.common.exceptions import ClientException, NotFound
24 0 from prettytable import PrettyTable
25 0 import yaml
26 0 import json
27 0 import time
28 0 import pycurl
29 0 import os
30 0 import textwrap
31 0 import pkg_resources
32 0 import logging
33 0 from datetime import datetime
34
35
36 # Global variables
37
38 0 CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'], max_content_width=160)
39
40 0 def wrap_text(text, width):
41 0     wrapper = textwrap.TextWrapper(width=width)
42 0     lines = text.splitlines()
43 0     return "\n".join(map(wrapper.fill, lines))
44
45
46 0 def trunc_text(text, length):
47 0    if len(text) > length:
48 0        return text[:(length - 3)] + '...'
49    else:
50 0        return text
51
52
53 0 def check_client_version(obj, what, version='sol005'):
54     """
55     Checks the version of the client object and raises error if it not the expected.
56
57     :param obj: the client object
58     :what: the function or command under evaluation (used when an error is raised)
59     :return: -
60     :raises ClientError: if the specified version does not match the client version
61     """
62 0     logger.debug("")
63 0     fullclassname = obj.__module__ + "." + obj.__class__.__name__
64 0     message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what)
65 0     if version == 'v1':
66 0         message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what)
67 0     if fullclassname != 'osmclient.{}.client.Client'.format(version):
68 0         raise ClientException(message)
69 0     return
70
71
72 0 def get_project(project_list, item):
73     # project_list = ctx.obj.project.list()
74 0     item_project_list = item.get('_admin', {}).get('projects_read')
75 0     project_id = 'None'
76 0     project_name = 'None'
77 0     if item_project_list:
78 0         for p1 in item_project_list:
79 0             project_id = p1
80 0             for p2 in project_list:
81 0                 if p2['_id'] == project_id:
82 0                     project_name = p2['name']
83 0                     return project_id, project_name
84 0     return project_id, project_name
85
86
87 0 def get_vim_name(vim_list, vim_id):
88 0     vim_name = '-'
89 0     for v in vim_list:
90 0         if v['uuid'] == vim_id:
91 0             vim_name = v['name']
92 0             break
93 0     return vim_name
94
95
96 0 @click.group(context_settings=dict(help_option_names=['-h', '--help'], max_content_width=160))
97 0 @click.option('--hostname',
98               default="127.0.0.1",
99               envvar='OSM_HOSTNAME',
100               help='hostname of server.  ' +
101                    'Also can set OSM_HOSTNAME in environment')
102 #@click.option('--sol005/--no-sol005',
103 #              default=True,
104 #              envvar='OSM_SOL005',
105 #              help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' +
106 #                   'Also can set OSM_SOL005 in environment')
107 0 @click.option('--user',
108               default=None,
109               envvar='OSM_USER',
110               help='user (defaults to admin). ' +
111                    'Also can set OSM_USER in environment')
112 0 @click.option('--password',
113               default=None,
114               envvar='OSM_PASSWORD',
115               help='password (defaults to admin). ' +
116                    'Also can set OSM_PASSWORD in environment')
117 0 @click.option('--project',
118               default=None,
119               envvar='OSM_PROJECT',
120               help='project (defaults to admin). ' +
121                    'Also can set OSM_PROJECT in environment')
122 0 @click.option('-v', '--verbose', count=True,
123               help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)')
124 0 @click.option('--all-projects',
125               default=None,
126               is_flag=True,
127               help='include all projects')
128 0 @click.option('--public/--no-public', default=None,
129               help='flag for public items (packages, instances, VIM accounts, etc.)')
130 0 @click.option('--project-domain-name', 'project_domain_name',
131               default=None,
132               envvar='OSM_PROJECT_DOMAIN_NAME',
133               help='project domain name for keystone authentication (default to None). ' +
134                    'Also can set OSM_PROJECT_DOMAIN_NAME in environment')
135 0 @click.option('--user-domain-name', 'user_domain_name',
136               default=None,
137               envvar='OSM_USER_DOMAIN_NAME',
138               help='user domain name for keystone authentication (default to None). ' +
139                    'Also can set OSM_USER_DOMAIN_NAME in environment')
140 #@click.option('--so-port',
141 #              default=None,
142 #              envvar='OSM_SO_PORT',
143 #              help='hostname of server.  ' +
144 #                   'Also can set OSM_SO_PORT in environment')
145 #@click.option('--so-project',
146 #              default=None,
147 #              envvar='OSM_SO_PROJECT',
148 #              help='Project Name in SO.  ' +
149 #                   'Also can set OSM_SO_PROJECT in environment')
150 #@click.option('--ro-hostname',
151 #              default=None,
152 #              envvar='OSM_RO_HOSTNAME',
153 #              help='hostname of RO server.  ' +
154 #              'Also can set OSM_RO_HOSTNAME in environment')
155 #@click.option('--ro-port',
156 #              default=None,
157 #              envvar='OSM_RO_PORT',
158 #              help='hostname of RO server.  ' +
159 #                   'Also can set OSM_RO_PORT in environment')
160 0 @click.pass_context
161 def cli_osm(ctx, **kwargs):
162     global logger
163 0     hostname = kwargs.pop("hostname", None)
164 0     if hostname is None:
165 0         print((
166             "either hostname option or OSM_HOSTNAME " +
167             "environment variable needs to be specified"))
168 0         exit(1)
169     # Remove None values
170 0     kwargs = {k: v for k, v in kwargs.items() if v is not None}
171 #    if so_port is not None:
172 #        kwargs['so_port']=so_port
173 #    if so_project is not None:
174 #        kwargs['so_project']=so_project
175 #    if ro_hostname is not None:
176 #        kwargs['ro_host']=ro_hostname
177 #    if ro_port is not None:
178 #        kwargs['ro_port']=ro_port
179 0     sol005 = os.getenv('OSM_SOL005', True)
180 #    if user is not None:
181 #        kwargs['user']=user
182 #    if password is not None:
183 #        kwargs['password']=password
184 #    if project is not None:
185 #        kwargs['project']=project
186 #    if all_projects:
187 #        kwargs['all_projects']=all_projects
188 #    if public is not None:
189 #        kwargs['public']=public
190 0     ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs)
191 0     logger = logging.getLogger('osmclient')
192
193
194 ####################
195 # LIST operations
196 ####################
197
198 0 @cli_osm.command(name='ns-list', short_help='list all NS instances')
199 0 @click.option('--filter', default=None, multiple=True,
200               help='restricts the list to the NS instances matching the filter.')
201 0 @click.option('--long', is_flag=True,
202               help='get more details of the NS (project, vim, deployment status, configuration status.')
203 0 @click.pass_context
204 def ns_list(ctx, filter, long):
205     """list all NS instances
206
207     \b
208     Options:
209       --filter filterExpr    Restricts the list to the NS instances matching the filter
210
211     \b
212     filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
213     concatenated using the "&" character:
214
215       \b
216       filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
217       simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
218       op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
219       attrName := string
220       value := scalar value
221
222     \b
223     where:
224       * zero or more occurrences
225       ? zero or one occurrence
226       [] grouping of expressions to be used with ? and *
227       "" quotation marks for marking string constants
228       <> name separator
229
230     \b
231     "AttrName" is the name of one attribute in the data type that defines the representation
232     of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
233     <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
234     "Op" stands for the comparison operator. If the expression has concatenated <attrName>
235     entries, it means that the operator "op" is applied to the attribute addressed by the last
236     <attrName> entry included in the concatenation. All simple filter expressions are combined
237     by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
238     the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
239     concatenation of all "attrName" entries except the leaf attribute is called the "attribute
240     prefix". If an attribute referenced in an expression is an array, an object that contains a
241     corresponding array shall be considered to match the expression if any of the elements in the
242     array matches all expressions that have the same attribute prefix.
243
244     \b
245     Filter examples:
246        --filter  admin-status=ENABLED
247        --filter  nsd-ref=<NSD_NAME>
248        --filter  nsd.vendor=<VENDOR>
249        --filter  nsd.vendor=<VENDOR>&nsd-ref=<NSD_NAME>
250        --filter  nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
251     """
252 0     def summarize_deployment_status(status_dict):
253         #Nets
254 0         summary = ""
255 0         if not status_dict:
256 0             return summary
257 0         n_nets = 0
258 0         status_nets = {}
259 0         net_list = status_dict.get('nets',[])
260 0         for net in net_list:
261 0             n_nets += 1
262 0             if net['status'] not in status_nets:
263 0                 status_nets[net['status']] = 1
264             else:
265 0                 status_nets[net['status']] +=1
266 0         message = "Nets: "
267 0         for k,v in status_nets.items():
268 0             message += "{}:{},".format(k,v)
269 0         message += "TOTAL:{}".format(n_nets)
270 0         summary += "{}".format(message)
271         #VMs and VNFs
272 0         n_vms = 0
273 0         status_vms = {}
274 0         status_vnfs = {}
275 0         vnf_list = status_dict['vnfs']
276 0         for vnf in vnf_list:
277 0             member_vnf_index = vnf['member_vnf_index']
278 0             if member_vnf_index not in status_vnfs:
279 0                 status_vnfs[member_vnf_index] = {}
280 0             for vm in vnf['vms']:
281 0                 n_vms += 1
282 0                 if vm['status'] not in status_vms:
283 0                     status_vms[vm['status']] = 1
284                 else:
285 0                     status_vms[vm['status']] +=1
286 0                 if vm['status'] not in status_vnfs[member_vnf_index]:
287 0                     status_vnfs[member_vnf_index][vm['status']] = 1
288                 else:
289 0                     status_vnfs[member_vnf_index][vm['status']] += 1
290 0         message = "VMs: "
291 0         for k,v in status_vms.items():
292 0             message += "{}:{},".format(k,v)
293 0         message += "TOTAL:{}".format(n_vms)
294 0         summary += "\n{}".format(message)
295 0         summary += "\nNFs:"
296 0         for k,v in status_vnfs.items():
297 0             total = 0
298 0             message = "\n  {} VMs: ".format(k)
299 0             for k2,v2 in v.items():
300 0                 message += "{}:{},".format(k2,v2)
301 0                 total += v2
302 0             message += "TOTAL:{}".format(total)
303 0         summary += message
304 0         return summary
305         
306 0     def summarize_config_status(ee_list):
307 0         summary = ""
308 0         if not ee_list:
309 0             return summary
310 0         n_ee = 0
311 0         status_ee = {}
312 0         for ee in ee_list:
313 0             n_ee += 1
314 0             if ee['elementType'] not in status_ee:
315 0                 status_ee[ee['elementType']] = {}
316 0                 status_ee[ee['elementType']][ee['status']] = 1
317 0                 continue
318 0             if ee['status'] in status_ee[ee['elementType']]:
319 0                 status_ee[ee['elementType']][ee['status']] += 1
320             else:
321 0                 status_ee[ee['elementType']][ee['status']] = 1
322 0         for elementType in ["KDU", "VDU", "PDU", "VNF", "NS"]:
323 0             if elementType in status_ee:
324 0                 message = ""
325 0                 total = 0
326 0                 for k,v in status_ee[elementType].items():
327 0                     message += "{}:{},".format(k,v)
328 0                     total += v
329 0                 message += "TOTAL:{}\n".format(total)
330 0                 summary += "{}: {}".format(elementType, message)
331 0         summary += "TOTAL Exec. Env.: {}".format(n_ee)
332 0         return summary
333
334 0     logger.debug("")
335 0     if filter:
336 0         check_client_version(ctx.obj, '--filter')
337 0         filter='&'.join(filter)
338 0         resp = ctx.obj.ns.list(filter)
339     else:
340 0         resp = ctx.obj.ns.list()
341 0     if long:
342 0         table = PrettyTable(
343         ['ns instance name',
344          'id',
345          'date',
346          'ns state',
347          'current operation',
348          'error details',
349          'project',
350          'vim (inst param)',
351          'deployment status',
352          'configuration status'])
353 0         project_list = ctx.obj.project.list()
354 0         try:
355 0             vim_list = ctx.obj.vim.list()
356 0         except:
357 0             vim_list = []
358     else:
359 0         table = PrettyTable(
360         ['ns instance name',
361          'id',
362          'date',
363          'ns state',
364          'current operation',
365          'error details'])
366 0     for ns in resp:
367 0         fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
368 0         if fullclassname == 'osmclient.sol005.client.Client':
369 0             nsr = ns
370 0             logger.debug('NS info: {}'.format(nsr))
371 0             nsr_name = nsr['name']
372 0             nsr_id = nsr['_id']
373 0             date = datetime.fromtimestamp(nsr['create-time']).strftime("%Y-%m-%dT%H:%M:%S")
374 0             ns_state = nsr.get('nsState', nsr['_admin']['nsState'])
375 0             if long:
376 0                 deployment_status = summarize_deployment_status(nsr.get('deploymentStatus'))
377 0                 config_status = summarize_config_status(nsr.get('configurationStatus'))
378 0                 project_id, project_name = get_project(project_list, nsr)
379                 #project = '{} ({})'.format(project_name, project_id)
380 0                 project = project_name
381 0                 vim_id = nsr.get('datacenter')
382 0                 vim_name = get_vim_name(vim_list, vim_id)
383
384                 #vim = '{} ({})'.format(vim_name, vim_id)
385 0                 vim = vim_name
386 0             if 'currentOperation' in nsr:
387 0                 current_operation = "{} ({})".format(nsr['currentOperation'],nsr['currentOperationID'])
388             else:
389 0                 current_operation = "{} ({})".format(nsr['_admin'].get('current-operation','-'), nsr['_admin']['nslcmop'])
390 0             error_details = "N/A"
391 0             if ns_state == "BROKEN" or ns_state == "DEGRADED" or \
392                 ('currentOperation' not in nsr and nsr.get('errorDescription')):
393 0                 error_details = "{}\nDetail: {}".format(nsr['errorDescription'], nsr['errorDetail'])
394         else:
395 0             nsopdata = ctx.obj.ns.get_opdata(ns['id'])
396 0             nsr = nsopdata['nsr:nsr']
397 0             nsr_name = nsr['name-ref']
398 0             nsr_id = nsr['ns-instance-config-ref']
399 0             date = '-'
400 0             project = '-'
401 0             deployment_status = nsr['operational-status'] if 'operational-status' in nsr else 'Not found'
402 0             ns_state = deployment_status
403 0             config_status = nsr.get('config-status', 'Not found')
404 0             current_operation = "Unknown"
405 0             error_details = nsr.get('detailed-status', 'Not found')
406 0             if config_status == "config_not_needed":
407 0                 config_status = "configured (no charms)"
408
409 0         if long:
410 0             table.add_row(
411                  [nsr_name,
412                  nsr_id,
413                  date,
414                  ns_state,
415                  current_operation,
416                  wrap_text(text=error_details,width=40),
417                  project,
418                  vim,
419                  deployment_status,
420                  config_status])
421         else:
422 0             table.add_row(
423                  [nsr_name,
424                  nsr_id,
425                  date,
426                  ns_state,
427                  current_operation,
428                  wrap_text(text=error_details,width=40)])
429 0     table.align = 'l'
430 0     print(table)
431 0     print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
432 0     print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"')
433
434 0 def nsd_list(ctx, filter, long):
435 0     logger.debug("")
436 0     if filter:
437 0         check_client_version(ctx.obj, '--filter')
438 0         filter='&'.join(filter)
439 0         resp = ctx.obj.nsd.list(filter)
440     else:
441 0         resp = ctx.obj.nsd.list()
442     # print(yaml.safe_dump(resp))
443 0     fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
444 0     if fullclassname == 'osmclient.sol005.client.Client':
445 0         if long:
446 0             table = PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state',
447                                  'usage state', 'date', 'last update'])
448         else:
449 0             table = PrettyTable(['nsd name', 'id'])
450 0         for nsd in resp:
451 0             name = nsd.get('id', '-')
452 0             if long:
453 0                 onb_state = nsd['_admin'].get('onboardingState','-')
454 0                 op_state = nsd['_admin'].get('operationalState','-')
455 0                 usage_state = nsd['_admin'].get('usageState','-')
456 0                 date = datetime.fromtimestamp(nsd['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
457 0                 last_update = datetime.fromtimestamp(nsd['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
458 0                 table.add_row([name, nsd['_id'], onb_state, op_state, usage_state, date, last_update])
459             else:
460 0                 table.add_row([name, nsd['_id']])
461     else:
462 0         table = PrettyTable(['nsd name', 'id'])
463 0         for nsd in resp:
464 0             table.add_row([nsd['name'], nsd['id']])
465 0     table.align = 'l'
466 0     print(table)
467
468
469 0 @cli_osm.command(name='nsd-list', short_help='list all NS packages')
470 0 @click.option('--filter', default=None, multiple=True,
471               help='restricts the list to the NSD/NSpkg matching the filter')
472 0 @click.option('--long', is_flag=True, help='get more details')
473 0 @click.pass_context
474 def nsd_list1(ctx, filter, long):
475     """list all NSD/NS pkg in the system"""
476 0     logger.debug("")
477 0     nsd_list(ctx, filter, long)
478
479
480 0 @cli_osm.command(name='nspkg-list', short_help='list all NS packages')
481 0 @click.option('--filter', default=None, multiple=True,
482               help='restricts the list to the NSD/NSpkg matching the filter')
483 0 @click.option('--long', is_flag=True, help='get more details')
484 0 @click.pass_context
485 def nsd_list2(ctx, filter, long):
486     """list all NS packages"""
487 0     logger.debug("")
488 0     nsd_list(ctx, filter, long)
489
490
491 0 def pkg_repo_list(ctx, pkgtype, filter, repo, long):
492 0     resp = ctx.obj.osmrepo.pkg_list(pkgtype, filter, repo)
493 0     if long:
494 0         table = PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository'])
495     else:
496 0         table = PrettyTable(['nfpkg name', 'repository'])
497 0     for vnfd in resp:
498 0         name = vnfd.get('id', vnfd.get('name','-'))
499 0         repository = vnfd.get('repository')
500 0         if long:
501 0             vendor = vnfd.get('provider', vnfd.get('vendor'))
502 0             version = vnfd.get('version')
503 0             description = vnfd.get('description')
504 0             latest = vnfd.get('latest')
505 0             table.add_row([name, vendor, version, latest, description, repository])
506         else:
507 0             table.add_row([name, repository])
508 0         table.align = 'l'
509 0     print(table)
510
511 0 def vnfd_list(ctx, nf_type, filter, long):
512 0     logger.debug("")
513 0     if nf_type:
514 0         check_client_version(ctx.obj, '--nf_type')
515 0     elif filter:
516 0         check_client_version(ctx.obj, '--filter')
517 0     if filter:
518 0         filter='&'.join(filter)
519 0     if nf_type:
520 0         if nf_type == "vnf":
521 0             nf_filter = "_admin.type=vnfd"
522 0         elif nf_type == "pnf":
523 0             nf_filter = "_admin.type=pnfd"
524 0         elif nf_type == "hnf":
525 0             nf_filter = "_admin.type=hnfd"
526         else:
527 0             raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf')
528 0         if filter:
529 0             filter = '{}&{}'.format(nf_filter, filter)
530         else:
531 0             filter = nf_filter
532 0     if filter:
533 0         resp = ctx.obj.vnfd.list(filter)
534     else:
535 0         resp = ctx.obj.vnfd.list()
536     # print(yaml.safe_dump(resp))
537 0     fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
538 0     if fullclassname == 'osmclient.sol005.client.Client':
539 0         if long:
540 0             table = PrettyTable(['nfpkg name', 'id', 'desc type', 'vendor', 'version', 'onboarding state', 'operational state',
541                                   'usage state', 'date', 'last update'])
542         else:
543 0             table = PrettyTable(['nfpkg name', 'id', 'desc type'])
544 0         for vnfd in resp:
545 0             name = vnfd.get('id', vnfd.get('name','-'))
546 0             descriptor_type = 'sol006' if 'product-name' in vnfd else 'rel8'
547 0             if long:
548 0                 onb_state = vnfd['_admin'].get('onboardingState','-')
549 0                 op_state = vnfd['_admin'].get('operationalState','-')
550 0                 vendor = vnfd.get('provider', vnfd.get('vendor'))
551 0                 version = vnfd.get('version')
552 0                 usage_state = vnfd['_admin'].get('usageState','-')
553 0                 date = datetime.fromtimestamp(vnfd['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
554 0                 last_update = datetime.fromtimestamp(vnfd['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
555 0                 table.add_row([name, vnfd['_id'], descriptor_type, vendor, version, onb_state, op_state, usage_state, date, last_update])
556             else:
557 0                 table.add_row([name, vnfd['_id'], descriptor_type])
558     else:
559 0         table = PrettyTable(['nfpkg name', 'id'])
560 0         for vnfd in resp:
561 0             table.add_row([vnfd['name'], vnfd['id']])
562 0     table.align = 'l'
563 0     print(table)
564
565
566 0 @cli_osm.command(name='vnfd-list', short_help='list all xNF packages (VNF, HNF, PNF)')
567 0 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
568 0 @click.option('--filter', default=None, multiple=True,
569               help='restricts the list to the NF pkg matching the filter')
570 0 @click.option('--long', is_flag=True, help='get more details')
571 0 @click.pass_context
572 def vnfd_list1(ctx, nf_type, filter, long):
573     """list all xNF packages (VNF, HNF, PNF)"""
574 0     logger.debug("")
575 0     vnfd_list(ctx, nf_type, filter, long)
576
577
578 0 @cli_osm.command(name='vnfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)')
579 0 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
580 0 @click.option('--filter', default=None, multiple=True,
581               help='restricts the list to the NFpkg matching the filter')
582 0 @click.option('--long', is_flag=True, help='get more details')
583 0 @click.pass_context
584 def vnfd_list2(ctx, nf_type, filter, long):
585     """list all xNF packages (VNF, HNF, PNF)"""
586 0     logger.debug("")
587 0     vnfd_list(ctx, nf_type, filter, long)
588
589
590 0 @cli_osm.command(name='nfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)')
591 0 @click.option('--nf_type', help='type of NF (vnf, pnf, hnf)')
592 0 @click.option('--filter', default=None, multiple=True,
593               help='restricts the list to the NFpkg matching the filter')
594 0 @click.option('--long', is_flag=True, help='get more details')
595 0 @click.pass_context
596 def nfpkg_list(ctx, nf_type, filter, long):
597     """list all xNF packages (VNF, HNF, PNF)"""
598 0     logger.debug("")
599     # try:
600 0     check_client_version(ctx.obj, ctx.command.name)
601 0     vnfd_list(ctx, nf_type, filter, long)
602     # except ClientException as e:
603     #     print(str(e))
604     #     exit(1)
605
606
607 0 @cli_osm.command(name='vnfpkg-repo-list', short_help='list all xNF from OSM repositories')
608 0 @click.option('--filter', default=None, multiple=True,
609               help='restricts the list to the NFpkg matching the filter')
610 0 @click.option('--repo', default=None,
611               help='restricts the list to a particular OSM repository')
612 0 @click.option('--long', is_flag=True, help='get more details')
613 0 @click.pass_context
614 def nfpkg_repo_list1(ctx, filter, repo, long):
615     """list xNF packages from OSM repositories"""
616 0     pkgtype = 'vnf'
617 0     pkg_repo_list(ctx, pkgtype, filter, repo, long)
618
619 0 @cli_osm.command(name='nfpkg-repo-list', short_help='list all xNF from OSM repositories')
620 0 @click.option('--filter', default=None, multiple=True,
621               help='restricts the list to the NFpkg matching the filter')
622 0 @click.option('--repo', default=None,
623               help='restricts the list to a particular OSM repository')
624 0 @click.option('--long', is_flag=True, help='get more details')
625 0 @click.pass_context
626 def nfpkg_repo_list2(ctx, filter, repo, long):
627     """list xNF packages from OSM repositories"""
628 0     pkgtype = 'vnf'
629 0     pkg_repo_list(ctx, pkgtype, filter, repo, long)
630
631
632 0 def vnf_list(ctx, ns, filter, long):
633     # try:
634 0     if ns or filter:
635 0         if ns:
636 0             check_client_version(ctx.obj, '--ns')
637 0         if filter:
638 0             filter='&'.join(filter)
639 0             check_client_version(ctx.obj, '--filter')
640 0         resp = ctx.obj.vnf.list(ns, filter)
641     else:
642 0         resp = ctx.obj.vnf.list()
643     # except ClientException as e:
644     #     print(str(e))
645     #     exit(1)
646 0     fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
647 0     if fullclassname == 'osmclient.sol005.client.Client':
648 0         field_names = ['vnf id', 'name', 'ns id', 'vnf member index',
649                        'vnfd name', 'vim account id', 'ip address']
650 0         if long:
651 0             field_names = ['vnf id', 'name', 'ns id', 'vnf member index',
652                            'vnfd name', 'vim account id', 'ip address',
653                            'date', 'last update']
654 0         table = PrettyTable(field_names)
655 0         for vnfr in resp:
656 0             name = vnfr['name'] if 'name' in vnfr else '-'
657 0             new_row = [vnfr['_id'], name, vnfr['nsr-id-ref'],
658                        vnfr['member-vnf-index-ref'], vnfr['vnfd-ref'],
659                        vnfr['vim-account-id'], vnfr['ip-address']]
660 0             if long:
661 0                 date = datetime.fromtimestamp(vnfr['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S")
662 0                 last_update = datetime.fromtimestamp(vnfr['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S")
663 0                 new_row.extend([date, last_update])
664 0             table.add_row(new_row)
665     else:
666 0         table = PrettyTable(
667             ['vnf name',
668              'id',
669              'operational status',
670              'config status'])
671 0         for vnfr in resp:
672 0             if 'mgmt-interface' not in vnfr:
673 0                 vnfr['mgmt-interface'] = {}
674 0                 vnfr['mgmt-interface']['ip-address'] = None
675 0             table.add_row(
676                 [vnfr['name'],
677                  vnfr['id'],
678                  vnfr['operational-status'],
679                  vnfr['config-status']])
680 0     table.align = 'l'
681 0     print(table)
682
683
684 0 @cli_osm.command(name='vnf-list', short_help='list all NF instances')
685 0 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
686 0 @click.option('--filter', default=None, multiple=True,
687               help='restricts the list to the NF instances matching the filter.')
688 0 @click.option('--long', is_flag=True, help='get more details')
689 0 @click.pass_context
690 def vnf_list1(ctx, ns, filter, long):
691     """list all NF instances"""
692 0     logger.debug("")
693 0     vnf_list(ctx, ns, filter, long)
694
695 0 @cli_osm.command(name='nsd-repo-list', short_help='list all NS from OSM repositories')
696 0 @click.option('--filter', default=None, multiple=True,
697               help='restricts the list to the NS matching the filter')
698 0 @click.option('--repo', default=None,
699               help='restricts the list to a particular OSM repository')
700 0 @click.option('--long', is_flag=True, help='get more details')
701 0 @click.pass_context
702 def nspkg_repo_list(ctx, filter, repo, long):
703     """list xNF packages from OSM repositories"""
704 0     pkgtype = 'ns'
705 0     pkg_repo_list(ctx, pkgtype, filter, repo, long)
706
707 0 @cli_osm.command(name='nspkg-repo-list', short_help='list all NS from OSM repositories')
708 0 @click.option('--filter', default=None, multiple=True,
709               help='restricts the list to the NS matching the filter')
710 0 @click.option('--repo', default=None,
711               help='restricts the list to a particular OSM repository')
712 0 @click.option('--long', is_flag=True, help='get more details')
713 0 @click.pass_context
714 def nspkg_repo_list2(ctx, filter, repo, long):
715     """list xNF packages from OSM repositories"""
716 0     pkgtype = 'ns'
717 0     pkg_repo_list(ctx, pkgtype, filter, repo, long)
718
719 0 @cli_osm.command(name='nf-list', short_help='list all NF instances')
720 0 @click.option('--ns', default=None, help='NS instance id or name to restrict the NF list')
721 0 @click.option('--filter', default=None, multiple=True,
722               help='restricts the list to the NF instances matching the filter.')
723 0 @click.option('--long', is_flag=True, help='get more details')
724 0 @click.pass_context
725 def nf_list(ctx, ns, filter, long):
726     """list all NF instances
727
728     \b
729     Options:
730       --ns     TEXT           NS instance id or name to restrict the VNF list
731       --filter filterExpr     Restricts the list to the VNF instances matching the filter
732
733     \b
734     filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
735     concatenated using the "&" character:
736
737       \b
738       filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
739       simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
740       op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
741       attrName := string
742       value := scalar value
743
744     \b
745     where:
746       * zero or more occurrences
747       ? zero or one occurrence
748       [] grouping of expressions to be used with ? and *
749       "" quotation marks for marking string constants
750       <> name separator
751
752     \b
753     "AttrName" is the name of one attribute in the data type that defines the representation
754     of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
755     <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
756     "Op" stands for the comparison operator. If the expression has concatenated <attrName>
757     entries, it means that the operator "op" is applied to the attribute addressed by the last
758     <attrName> entry included in the concatenation. All simple filter expressions are combined
759     by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
760     the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
761     concatenation of all "attrName" entries except the leaf attribute is called the "attribute
762     prefix". If an attribute referenced in an expression is an array, an object that contains a
763     corresponding array shall be considered to match the expression if any of the elements in the
764     array matches all expressions that have the same attribute prefix.
765
766     \b
767     Filter examples:
768        --filter  vim-account-id=<VIM_ACCOUNT_ID>
769        --filter  vnfd-ref=<VNFD_NAME>
770        --filter  vdur.ip-address=<IP_ADDRESS>
771        --filter  vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
772     """
773 0     logger.debug("")
774 0     vnf_list(ctx, ns, filter, long)
775
776
777 0 @cli_osm.command(name='ns-op-list', short_help='shows the history of operations over a NS instance')
778 0 @click.argument('name')
779 0 @click.option('--long', is_flag=True,
780               help='get more details of the NS operation (date, ).')
781 0 @click.pass_context
782 def ns_op_list(ctx, name, long):
783     """shows the history of operations over a NS instance
784
785     NAME: name or ID of the NS instance
786     """
787 0     def formatParams(params):
788 0         if params['lcmOperationType']=='instantiate':
789 0             params.pop('nsDescription')
790 0             params.pop('nsName')
791 0             params.pop('nsdId')
792 0             params.pop('nsr_id')
793 0         elif params['lcmOperationType']=='action':
794 0             params.pop('primitive')
795 0         params.pop('lcmOperationType')
796 0         params.pop('nsInstanceId')
797 0         return params
798
799 0     logger.debug("")
800     # try:
801 0     check_client_version(ctx.obj, ctx.command.name)
802 0     resp = ctx.obj.ns.list_op(name)
803     # except ClientException as e:
804     #     print(str(e))
805     #     exit(1)
806
807 0     if long:
808 0         table = PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail'])
809     else:
810 0         table = PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail'])
811
812     #print(yaml.safe_dump(resp))
813 0     for op in resp:
814 0         action_name = "N/A"
815 0         if op['lcmOperationType']=='action':
816 0             action_name = op['operationParams']['primitive']
817 0         detail = "-"
818 0         if op['operationState'] == 'PROCESSING':
819 0             if op['queuePosition'] is not None and op['queuePosition'] > 0:
820 0                 detail = "In queue. Current position: {}".format(op['queuePosition'])
821 0             elif op['lcmOperationType'] in ('instantiate', 'terminate'):
822 0                 if op['stage']:
823 0                     detail = op['stage']
824 0         elif op['operationState'] in ('FAILED', 'FAILED_TEMP'):
825 0             detail = op.get('errorMessage','-')
826 0         date = datetime.fromtimestamp(op['startTime']).strftime("%Y-%m-%dT%H:%M:%S")
827 0         last_update = datetime.fromtimestamp(op['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S")
828 0         if long:
829 0             table.add_row([op['id'],
830                            op['lcmOperationType'],
831                            action_name,
832                            wrap_text(text=json.dumps(formatParams(op['operationParams']),indent=2),width=50),
833                            op['operationState'],
834                            date,
835                            last_update,
836                            wrap_text(text=detail,width=50)])
837         else:
838 0             table.add_row([op['id'], op['lcmOperationType'], action_name,
839                            op['operationState'], date, wrap_text(text=detail or "",width=50)])
840 0     table.align = 'l'
841 0     print(table)
842
843
844 0 def nsi_list(ctx, filter):
845     """list all Network Slice Instances"""
846 0     logger.debug("")
847     # try:
848 0     check_client_version(ctx.obj, ctx.command.name)
849 0     if filter:
850 0         filter='&'.join(filter)
851 0     resp = ctx.obj.nsi.list(filter)
852     # except ClientException as e:
853     #     print(str(e))
854     #     exit(1)
855 0     table = PrettyTable(
856         ['netslice instance name',
857          'id',
858          'operational status',
859          'config status',
860          'detailed status'])
861 0     for nsi in resp:
862 0         nsi_name = nsi['name']
863 0         nsi_id = nsi['_id']
864 0         opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found'
865 0         configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found'
866 0         detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found'
867 0         if configstatus == "config_not_needed":
868 0             configstatus = "configured (no charms)"
869 0         table.add_row(
870             [nsi_name,
871              nsi_id,
872              opstatus,
873              configstatus,
874              detailed_status])
875 0     table.align = 'l'
876 0     print(table)
877
878
879 0 @cli_osm.command(name='nsi-list', short_help='list all Network Slice Instances (NSI)')
880 0 @click.option('--filter', default=None, multiple=True,
881               help='restricts the list to the Network Slice Instances matching the filter')
882 0 @click.pass_context
883 def nsi_list1(ctx, filter):
884     """list all Network Slice Instances (NSI)"""
885 0     logger.debug("")
886 0     nsi_list(ctx, filter)
887
888
889 0 @cli_osm.command(name='netslice-instance-list', short_help='list all Network Slice Instances (NSI)')
890 0 @click.option('--filter', default=None, multiple=True,
891               help='restricts the list to the Network Slice Instances matching the filter')
892 0 @click.pass_context
893 def nsi_list2(ctx, filter):
894     """list all Network Slice Instances (NSI)"""
895 0     logger.debug("")
896 0     nsi_list(ctx, filter)
897
898
899 0 def nst_list(ctx, filter):
900 0     logger.debug("")
901     # try:
902 0     check_client_version(ctx.obj, ctx.command.name)
903 0     if filter:
904 0         filter='&'.join(filter)
905 0     resp = ctx.obj.nst.list(filter)
906     # except ClientException as e:
907     #     print(str(e))
908     #     exit(1)
909     # print(yaml.safe_dump(resp))
910 0     table = PrettyTable(['nst name', 'id'])
911 0     for nst in resp:
912 0         name = nst['name'] if 'name' in nst else '-'
913 0         table.add_row([name, nst['_id']])
914 0     table.align = 'l'
915 0     print(table)
916
917
918 0 @cli_osm.command(name='nst-list', short_help='list all Network Slice Templates (NST)')
919 0 @click.option('--filter', default=None, multiple=True,
920               help='restricts the list to the NST matching the filter')
921 0 @click.pass_context
922 def nst_list1(ctx, filter):
923     """list all Network Slice Templates (NST) in the system"""
924 0     logger.debug("")
925 0     nst_list(ctx, filter)
926
927
928 0 @cli_osm.command(name='netslice-template-list', short_help='list all Network Slice Templates (NST)')
929 0 @click.option('--filter', default=None, multiple=True,
930               help='restricts the list to the NST matching the filter')
931 0 @click.pass_context
932 def nst_list2(ctx, filter):
933     """list all Network Slice Templates (NST) in the system"""
934 0     logger.debug("")
935 0     nst_list(ctx, filter)
936
937
938 0 def nsi_op_list(ctx, name):
939 0     logger.debug("")
940     # try:
941 0     check_client_version(ctx.obj, ctx.command.name)
942 0     resp = ctx.obj.nsi.list_op(name)
943     # except ClientException as e:
944     #     print(str(e))
945     #     exit(1)
946 0     table = PrettyTable(['id', 'operation', 'status'])
947 0     for op in resp:
948 0         table.add_row([op['id'], op['lcmOperationType'],
949                        op['operationState']])
950 0     table.align = 'l'
951 0     print(table)
952
953
954 0 @cli_osm.command(name='nsi-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)')
955 0 @click.argument('name')
956 0 @click.pass_context
957 def nsi_op_list1(ctx, name):
958     """shows the history of operations over a Network Slice Instance (NSI)
959
960     NAME: name or ID of the Network Slice Instance
961     """
962 0     logger.debug("")
963 0     nsi_op_list(ctx, name)
964
965
966 0 @cli_osm.command(name='netslice-instance-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)')
967 0 @click.argument('name')
968 0 @click.pass_context
969 def nsi_op_list2(ctx, name):
970     """shows the history of operations over a Network Slice Instance (NSI)
971
972     NAME: name or ID of the Network Slice Instance
973     """
974 0     logger.debug("")
975 0     nsi_op_list(ctx, name)
976
977
978 0 @cli_osm.command(name='pdu-list', short_help='list all Physical Deployment Units (PDU)')
979 0 @click.option('--filter', default=None, multiple=True,
980               help='restricts the list to the Physical Deployment Units matching the filter')
981 0 @click.pass_context
982 def pdu_list(ctx, filter):
983     """list all Physical Deployment Units (PDU)"""
984 0     logger.debug("")
985     # try:
986 0     check_client_version(ctx.obj, ctx.command.name)
987 0     if filter:
988 0         filter='&'.join(filter)
989 0     resp = ctx.obj.pdu.list(filter)
990     # except ClientException as e:
991     #     print(str(e))
992     #     exit(1)
993 0     table = PrettyTable(
994         ['pdu name',
995          'id',
996          'type',
997          'mgmt ip address'])
998 0     for pdu in resp:
999 0         pdu_name = pdu['name']
1000 0         pdu_id = pdu['_id']
1001 0         pdu_type = pdu['type']
1002 0         pdu_ipaddress = "None"
1003 0         for iface in pdu['interfaces']:
1004 0             if iface['mgmt']:
1005 0                 pdu_ipaddress = iface['ip-address']
1006 0                 break
1007 0         table.add_row(
1008             [pdu_name,
1009              pdu_id,
1010              pdu_type,
1011              pdu_ipaddress])
1012 0     table.align = 'l'
1013 0     print(table)
1014
1015
1016 ####################
1017 # SHOW operations
1018 ####################
1019
1020 0 def nsd_show(ctx, name, literal):
1021 0     logger.debug("")
1022     # try:
1023 0     resp = ctx.obj.nsd.get(name)
1024     # resp = ctx.obj.nsd.get_individual(name)
1025     # except ClientException as e:
1026     #     print(str(e))
1027     #     exit(1)
1028
1029 0     if literal:
1030 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1031 0         return
1032
1033 0     table = PrettyTable(['field', 'value'])
1034 0     for k, v in list(resp.items()):
1035 0         table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
1036 0     table.align = 'l'
1037 0     print(table)
1038
1039
1040 0 @cli_osm.command(name='nsd-show', short_help='shows the details of a NS package')
1041 0 @click.option('--literal', is_flag=True,
1042               help='print literally, no pretty table')
1043 0 @click.argument('name')
1044 0 @click.pass_context
1045 def nsd_show1(ctx, name, literal):
1046     """shows the content of a NSD
1047
1048     NAME: name or ID of the NSD/NSpkg
1049     """
1050 0     logger.debug("")
1051 0     nsd_show(ctx, name, literal)
1052
1053
1054 0 @cli_osm.command(name='nspkg-show', short_help='shows the details of a NS package')
1055 0 @click.option('--literal', is_flag=True,
1056               help='print literally, no pretty table')
1057 0 @click.argument('name')
1058 0 @click.pass_context
1059 def nsd_show2(ctx, name, literal):
1060     """shows the content of a NSD
1061
1062     NAME: name or ID of the NSD/NSpkg
1063     """
1064 0     logger.debug("")
1065 0     nsd_show(ctx, name, literal)
1066
1067
1068 0 def vnfd_show(ctx, name, literal):
1069 0     logger.debug("")
1070     # try:
1071 0     resp = ctx.obj.vnfd.get(name)
1072     # resp = ctx.obj.vnfd.get_individual(name)
1073     # except ClientException as e:
1074     #     print(str(e))
1075     #     exit(1)
1076
1077 0     if literal:
1078 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1079 0         return
1080
1081 0     table = PrettyTable(['field', 'value'])
1082 0     for k, v in list(resp.items()):
1083 0         table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
1084 0     table.align = 'l'
1085 0     print(table)
1086
1087
1088 0 def pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal):
1089 0     logger.debug("")
1090 0     if filter:
1091 0         filter='&'.join(filter)
1092     # try:
1093 0     resp = ctx.obj.osmrepo.pkg_get(pkgtype, name, repo, version, filter)
1094
1095 0     if literal:
1096 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1097 0         return
1098 0     pkgtype += 'd'
1099 0     catalog = pkgtype + '-catalog'
1100 0     full_catalog = pkgtype + ':' + catalog
1101 0     if resp.get(catalog):
1102 0         resp = resp.pop(catalog)[pkgtype][0]
1103 0     elif resp.get(full_catalog):
1104 0         resp = resp.pop(full_catalog)[pkgtype][0]
1105
1106 0     table = PrettyTable(['field', 'value'])
1107 0     for k, v in list(resp.items()):
1108 0         table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
1109 0     table.align = 'l'
1110 0     print(table)
1111
1112
1113 0 @cli_osm.command(name='vnfd-show', short_help='shows the details of a NF package')
1114 0 @click.option('--literal', is_flag=True,
1115               help='print literally, no pretty table')
1116 0 @click.argument('name')
1117 0 @click.pass_context
1118 def vnfd_show1(ctx, name, literal):
1119     """shows the content of a VNFD
1120
1121     NAME: name or ID of the VNFD/VNFpkg
1122     """
1123 0     logger.debug("")
1124 0     vnfd_show(ctx, name, literal)
1125
1126
1127 0 @cli_osm.command(name='vnfpkg-show', short_help='shows the details of a NF package')
1128 0 @click.option('--literal', is_flag=True,
1129               help='print literally, no pretty table')
1130 0 @click.argument('name')
1131 0 @click.pass_context
1132 def vnfd_show2(ctx, name, literal):
1133     """shows the content of a VNFD
1134
1135     NAME: name or ID of the VNFD/VNFpkg
1136     """
1137 0     logger.debug("")
1138 0     vnfd_show(ctx, name, literal)
1139
1140 0 @cli_osm.command(name='vnfpkg-repo-show', short_help='shows the details of a NF package in an OSM repository')
1141 0 @click.option('--literal', is_flag=True,
1142               help='print literally, no pretty table')
1143 0 @click.option('--repo',
1144               required=True,
1145               help='Repository name')
1146 0 @click.argument('name')
1147 0 @click.option('--filter', default=None, multiple=True,
1148               help='filter by fields')
1149 0 @click.option('--version',
1150               default='latest',
1151               help='package version')
1152 0 @click.pass_context
1153 0 def vnfd_show3(ctx, name, repo, version, literal=None, filter=None):
1154     """shows the content of a VNFD in a repository
1155
1156     NAME: name or ID of the VNFD/VNFpkg
1157     """
1158 0     pkgtype = 'vnf'
1159 0     pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1160
1161
1162 0 @cli_osm.command(name='nsd-repo-show', short_help='shows the details of a NS package in an OSM repository')
1163 0 @click.option('--literal', is_flag=True,
1164               help='print literally, no pretty table')
1165 0 @click.option('--repo',
1166               required=True,
1167               help='Repository name')
1168 0 @click.argument('name')
1169 0 @click.option('--filter', default=None, multiple=True,
1170               help='filter by fields')
1171 0 @click.option('--version',
1172               default='latest',
1173               help='package version')
1174 0 @click.pass_context
1175 0 def nsd_repo_show(ctx, name, repo, version, literal=None, filter=None):
1176     """shows the content of a VNFD in a repository
1177
1178     NAME: name or ID of the VNFD/VNFpkg
1179     """
1180 0     pkgtype = 'ns'
1181 0     pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1182
1183 0 @cli_osm.command(name='nspkg-repo-show', short_help='shows the details of a NS package in an OSM repository')
1184 0 @click.option('--literal', is_flag=True,
1185               help='print literally, no pretty table')
1186 0 @click.option('--repo',
1187               required=True,
1188               help='Repository name')
1189 0 @click.argument('name')
1190 0 @click.option('--filter', default=None, multiple=True,
1191               help='filter by fields')
1192 0 @click.option('--version',
1193               default='latest',
1194               help='package version')
1195 0 @click.pass_context
1196 0 def nsd_repo_show2(ctx, name, repo, version, literal=None, filter=None):
1197     """shows the content of a VNFD in a repository
1198
1199     NAME: name or ID of the VNFD/VNFpkg
1200     """
1201 0     pkgtype = 'ns'
1202 0     pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1203
1204
1205 0 @cli_osm.command(name='nfpkg-show', short_help='shows the details of a NF package')
1206 0 @click.option('--literal', is_flag=True,
1207               help='print literally, no pretty table')
1208 0 @click.argument('name')
1209 0 @click.pass_context
1210 def nfpkg_show(ctx, name, literal):
1211     """shows the content of a NF Descriptor
1212
1213     NAME: name or ID of the NFpkg
1214     """
1215 0     logger.debug("")
1216 0     vnfd_show(ctx, name, literal)
1217
1218
1219 0 @cli_osm.command(name='nfpkg-repo-show', short_help='shows the details of a NF package in an OSM repository')
1220 0 @click.option('--literal', is_flag=True,
1221               help='print literally, no pretty table')
1222 0 @click.option('--repo',
1223               required=True,
1224               help='Repository name')
1225 0 @click.argument('name')
1226 0 @click.option('--filter', default=None, multiple=True,
1227               help='filter by fields')
1228 0 @click.option('--version',
1229               default='latest',
1230               help='package version')
1231 0 @click.pass_context
1232 0 def vnfd_show4(ctx, name, repo, version, literal=None, filter=None):
1233     """shows the content of a VNFD in a repository
1234
1235     NAME: name or ID of the VNFD/VNFpkg
1236     """
1237 0     pkgtype = 'vnf'
1238 0     pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
1239
1240
1241 0 @cli_osm.command(name='ns-show', short_help='shows the info of a NS instance')
1242 0 @click.argument('name')
1243 0 @click.option('--literal', is_flag=True,
1244               help='print literally, no pretty table')
1245 0 @click.option('--filter', multiple=True,
1246               help='restricts the information to the fields in the filter')
1247 0 @click.pass_context
1248 def ns_show(ctx, name, literal, filter):
1249     """shows the info of a NS instance
1250
1251     NAME: name or ID of the NS instance
1252     """
1253 0     logger.debug("")
1254     # try:
1255 0     ns = ctx.obj.ns.get(name)
1256     # except ClientException as e:
1257     #     print(str(e))
1258     #     exit(1)
1259
1260 0     if literal:
1261 0         print(yaml.safe_dump(ns, indent=4, default_flow_style=False))
1262 0         return
1263
1264 0     table = PrettyTable(['field', 'value'])
1265
1266 0     for k, v in list(ns.items()):
1267 0         if not filter or k in filter:
1268 0             table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
1269
1270 0     fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
1271 0     if fullclassname != 'osmclient.sol005.client.Client':
1272 0         nsopdata = ctx.obj.ns.get_opdata(ns['id'])
1273 0         nsr_optdata = nsopdata['nsr:nsr']
1274 0         for k, v in list(nsr_optdata.items()):
1275 0             if not filter or k in filter:
1276 0                 table.add_row([k, wrap_text(json.dumps(v, indent=2),width=100)])
1277 0     table.align = 'l'
1278 0     print(table)
1279
1280
1281 0 @cli_osm.command(name='vnf-show', short_help='shows the info of a VNF instance')
1282 0 @click.argument('name')
1283 0 @click.option('--literal', is_flag=True,
1284               help='print literally, no pretty table')
1285 0 @click.option('--filter', multiple=True,
1286               help='restricts the information to the fields in the filter')
1287 0 @click.option('--kdu', default=None, help='KDU name (whose status will be shown)')
1288 0 @click.pass_context
1289 def vnf_show(ctx, name, literal, filter, kdu):
1290     """shows the info of a VNF instance
1291
1292     NAME: name or ID of the VNF instance
1293     """
1294 0     def print_kdu_status(op_info_status):
1295         """print KDU status properly formatted
1296         """
1297 0         try:
1298 0             op_status = yaml.safe_load(op_info_status)
1299 0             if "namespace" in op_status and "info" in op_status and \
1300             "last_deployed" in op_status["info"] and "status" in op_status["info"] and \
1301             "code" in op_status["info"]["status"] and "resources" in op_status["info"]["status"] and \
1302             "seconds" in op_status["info"]["last_deployed"]:
1303 0                 last_deployed_time = datetime.fromtimestamp(op_status["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y")
1304 0                 print("LAST DEPLOYED: {}".format(last_deployed_time))
1305 0                 print("NAMESPACE: {}".format(op_status["namespace"]))
1306 0                 status_code = "UNKNOWN"
1307 0                 if op_status["info"]["status"]["code"]==1:
1308 0                     status_code = "DEPLOYED"
1309 0                 print("STATUS: {}".format(status_code))
1310 0                 print()
1311 0                 print("RESOURCES:")
1312 0                 print(op_status["info"]["status"]["resources"])
1313 0                 if "notes" in op_status["info"]["status"]:
1314 0                     print("NOTES:")
1315 0                     print(op_status["info"]["status"]["notes"])
1316             else:
1317 0                 print(op_info_status)
1318 0         except Exception:
1319 0             print(op_info_status)
1320
1321 0     logger.debug("")
1322 0     if kdu:
1323 0         if literal:
1324 0             raise ClientException('"--literal" option is incompatible with "--kdu" option')
1325 0         if filter:
1326 0             raise ClientException('"--filter" option is incompatible with "--kdu" option')
1327
1328     # try:
1329 0     check_client_version(ctx.obj, ctx.command.name)
1330 0     resp = ctx.obj.vnf.get(name)
1331
1332 0     if kdu:
1333 0         ns_id = resp['nsr-id-ref']
1334 0         op_data={}
1335 0         op_data['member_vnf_index'] = resp['member-vnf-index-ref']
1336 0         op_data['kdu_name'] = kdu
1337 0         op_data['primitive'] = 'status'
1338 0         op_data['primitive_params'] = {}
1339 0         op_id = ctx.obj.ns.exec_op(ns_id, op_name='action', op_data=op_data, wait=False)
1340 0         t = 0
1341 0         while t<30:
1342 0             op_info = ctx.obj.ns.get_op(op_id)
1343 0             if op_info['operationState'] == 'COMPLETED':
1344 0                 print_kdu_status(op_info['detailed-status'])
1345 0                 return
1346 0             time.sleep(5)
1347 0             t += 5
1348 0         print ("Could not determine KDU status")
1349 0         return
1350
1351 0     if literal:
1352 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1353 0         return
1354
1355 0     table = PrettyTable(['field', 'value'])
1356 0     for k, v in list(resp.items()):
1357 0         if not filter or k in filter:
1358 0             table.add_row([k, wrap_text(text=json.dumps(v,indent=2),width=100)])
1359 0     table.align = 'l'
1360 0     print(table)
1361     # except ClientException as e:
1362     #     print(str(e))
1363     #     exit(1)
1364
1365
1366 #@cli_osm.command(name='vnf-monitoring-show')
1367 #@click.argument('vnf_name')
1368 #@click.pass_context
1369 #def vnf_monitoring_show(ctx, vnf_name):
1370 #    try:
1371 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
1372 #        resp = ctx.obj.vnf.get_monitoring(vnf_name)
1373 #    except ClientException as e:
1374 #        print(str(e))
1375 #        exit(1)
1376 #
1377 #    table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1378 #    if resp is not None:
1379 #        for monitor in resp:
1380 #            table.add_row(
1381 #                [vnf_name,
1382 #                 monitor['name'],
1383 #                    monitor['value-integer'],
1384 #                    monitor['units']])
1385 #    table.align = 'l'
1386 #    print(table)
1387
1388
1389 #@cli_osm.command(name='ns-monitoring-show')
1390 #@click.argument('ns_name')
1391 #@click.pass_context
1392 #def ns_monitoring_show(ctx, ns_name):
1393 #    try:
1394 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
1395 #        resp = ctx.obj.ns.get_monitoring(ns_name)
1396 #    except ClientException as e:
1397 #        print(str(e))
1398 #        exit(1)
1399 #
1400 #    table = PrettyTable(['vnf name', 'monitoring name', 'value', 'units'])
1401 #    for key, val in list(resp.items()):
1402 #        for monitor in val:
1403 #            table.add_row(
1404 #                [key,
1405 #                 monitor['name'],
1406 #                    monitor['value-integer'],
1407 #                    monitor['units']])
1408 #    table.align = 'l'
1409 #    print(table)
1410
1411
1412 0 @cli_osm.command(name='ns-op-show', short_help='shows the info of a NS operation')
1413 0 @click.argument('id')
1414 0 @click.option('--filter', multiple=True,
1415               help='restricts the information to the fields in the filter')
1416 0 @click.option('--literal', is_flag=True,
1417               help='print literally, no pretty table')
1418 0 @click.pass_context
1419 def ns_op_show(ctx, id, filter, literal):
1420     """shows the detailed info of a NS operation
1421
1422     ID: operation identifier
1423     """
1424 0     logger.debug("")
1425     # try:
1426 0     check_client_version(ctx.obj, ctx.command.name)
1427 0     op_info = ctx.obj.ns.get_op(id)
1428     # except ClientException as e:
1429     #     print(str(e))
1430     #     exit(1)
1431
1432 0     if literal:
1433 0         print(yaml.safe_dump(op_info, indent=4, default_flow_style=False))
1434 0         return
1435
1436 0     table = PrettyTable(['field', 'value'])
1437 0     for k, v in list(op_info.items()):
1438 0         if not filter or k in filter:
1439 0             table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
1440 0     table.align = 'l'
1441 0     print(table)
1442
1443
1444 0 def nst_show(ctx, name, literal):
1445 0     logger.debug("")
1446     # try:
1447 0     check_client_version(ctx.obj, ctx.command.name)
1448 0     resp = ctx.obj.nst.get(name)
1449     #resp = ctx.obj.nst.get_individual(name)
1450     # except ClientException as e:
1451     #     print(str(e))
1452     #     exit(1)
1453
1454 0     if literal:
1455 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
1456 0         return
1457
1458 0     table = PrettyTable(['field', 'value'])
1459 0     for k, v in list(resp.items()):
1460 0         table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)])
1461 0     table.align = 'l'
1462 0     print(table)
1463
1464
1465 0 @cli_osm.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)')
1466 0 @click.option('--literal', is_flag=True,
1467               help='print literally, no pretty table')
1468 0 @click.argument('name')
1469 0 @click.pass_context
1470 def nst_show1(ctx, name, literal):
1471     """shows the content of a Network Slice Template (NST)
1472
1473     NAME: name or ID of the NST
1474     """
1475 0     logger.debug("")
1476 0     nst_show(ctx, name, literal)
1477
1478
1479 0 @cli_osm.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)')
1480 0 @click.option('--literal', is_flag=True,
1481               help='print literally, no pretty table')
1482 0 @click.argument('name')
1483 0 @click.pass_context
1484 def nst_show2(ctx, name, literal):
1485     """shows the content of a Network Slice Template (NST)
1486
1487     NAME: name or ID of the NST
1488     """
1489 0     logger.debug("")
1490 0     nst_show(ctx, name, literal)
1491
1492
1493 0 def nsi_show(ctx, name, literal, filter):
1494 0     logger.debug("")
1495     # try:
1496 0     check_client_version(ctx.obj, ctx.command.name)
1497 0     nsi = ctx.obj.nsi.get(name)
1498     # except ClientException as e:
1499     #     print(str(e))
1500     #     exit(1)
1501
1502 0     if literal:
1503 0         print(yaml.safe_dump(nsi, indent=4, default_flow_style=False))
1504 0         return
1505
1506 0     table = PrettyTable(['field', 'value'])
1507
1508 0     for k, v in list(nsi.items()):
1509 0         if not filter or k in filter:
1510 0             table.add_row([k, json.dumps(v, indent=2)])
1511
1512 0     table.align = 'l'
1513 0     print(table)
1514
1515
1516 0 @cli_osm.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)')
1517 0 @click.argument('name')
1518 0 @click.option('--literal', is_flag=True,
1519               help='print literally, no pretty table')
1520 0 @click.option('--filter', multiple=True,
1521               help='restricts the information to the fields in the filter')
1522 0 @click.pass_context
1523 def nsi_show1(ctx, name, literal, filter):
1524     """shows the content of a Network Slice Instance (NSI)
1525
1526     NAME: name or ID of the Network Slice Instance
1527     """
1528 0     logger.debug("")
1529 0     nsi_show(ctx, name, literal, filter)
1530
1531
1532 0 @cli_osm.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)')
1533 0 @click.argument('name')
1534 0 @click.option('--literal', is_flag=True,
1535               help='print literally, no pretty table')
1536 0 @click.option('--filter', multiple=True,
1537               help='restricts the information to the fields in the filter')
1538 0 @click.pass_context
1539 def nsi_show2(ctx, name, literal, filter):
1540     """shows the content of a Network Slice Instance (NSI)
1541
1542     NAME: name or ID of the Network Slice Instance
1543     """
1544 0     logger.debug("")
1545 0     nsi_show(ctx, name, literal, filter)
1546
1547
1548 0 def nsi_op_show(ctx, id, filter):
1549 0     logger.debug("")
1550     # try:
1551 0     check_client_version(ctx.obj, ctx.command.name)
1552 0     op_info = ctx.obj.nsi.get_op(id)
1553     # except ClientException as e:
1554     #     print(str(e))
1555     #     exit(1)
1556
1557 0     table = PrettyTable(['field', 'value'])
1558 0     for k, v in list(op_info.items()):
1559 0         if not filter or k in filter:
1560 0             table.add_row([k, json.dumps(v, indent=2)])
1561 0     table.align = 'l'
1562 0     print(table)
1563
1564
1565 0 @cli_osm.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
1566 0 @click.argument('id')
1567 0 @click.option('--filter', multiple=True,
1568               help='restricts the information to the fields in the filter')
1569 0 @click.pass_context
1570 def nsi_op_show1(ctx, id, filter):
1571     """shows the info of an operation over a Network Slice Instance(NSI)
1572
1573     ID: operation identifier
1574     """
1575 0     logger.debug("")
1576 0     nsi_op_show(ctx, id, filter)
1577
1578
1579 0 @cli_osm.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)')
1580 0 @click.argument('id')
1581 0 @click.option('--filter', multiple=True,
1582               help='restricts the information to the fields in the filter')
1583 0 @click.pass_context
1584 def nsi_op_show2(ctx, id, filter):
1585     """shows the info of an operation over a Network Slice Instance(NSI)
1586
1587     ID: operation identifier
1588     """
1589 0     logger.debug("")
1590 0     nsi_op_show(ctx, id, filter)
1591
1592
1593 0 @cli_osm.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)')
1594 0 @click.argument('name')
1595 0 @click.option('--literal', is_flag=True,
1596               help='print literally, no pretty table')
1597 0 @click.option('--filter', multiple=True,
1598               help='restricts the information to the fields in the filter')
1599 0 @click.pass_context
1600 def pdu_show(ctx, name, literal, filter):
1601     """shows the content of a Physical Deployment Unit (PDU)
1602
1603     NAME: name or ID of the PDU
1604     """
1605 0     logger.debug("")
1606     # try:
1607 0     check_client_version(ctx.obj, ctx.command.name)
1608 0     pdu = ctx.obj.pdu.get(name)
1609     # except ClientException as e:
1610     #     print(str(e))
1611     #     exit(1)
1612
1613 0     if literal:
1614 0         print(yaml.safe_dump(pdu, indent=4, default_flow_style=False))
1615 0         return
1616
1617 0     table = PrettyTable(['field', 'value'])
1618
1619 0     for k, v in list(pdu.items()):
1620 0         if not filter or k in filter:
1621 0             table.add_row([k, json.dumps(v, indent=2)])
1622
1623 0     table.align = 'l'
1624 0     print(table)
1625
1626
1627 ####################
1628 # CREATE operations
1629 ####################
1630
1631 0 def nsd_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version):
1632 0     logger.debug("")
1633     # try:
1634 0     check_client_version(ctx.obj, ctx.command.name)
1635 0     if repo:
1636 0         filename = ctx.obj.osmrepo.get_pkg('ns', filename, repo, vendor, version)
1637 0     ctx.obj.nsd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build)
1638     # except ClientException as e:
1639     #     print(str(e))
1640     #     exit(1)
1641
1642
1643 0 @cli_osm.command(name='nsd-create', short_help='creates a new NSD/NSpkg')
1644 0 @click.argument('filename')
1645 0 @click.option('--overwrite', 'overwrite', default=None,  # hidden=True,
1646               help='Deprecated. Use override')
1647 0 @click.option('--override', 'overwrite', default=None,
1648               help='overrides fields in descriptor, format: '
1649                    '"key1.key2...=value[;key3...=value;...]"')
1650 0 @click.option('--skip-charm-build', default=False, is_flag=True,
1651               help='The charm will not be compiled, it is assumed to already exist')
1652 0 @click.option('--repo', default=None,
1653               help='[repository]: Repository name')
1654 0 @click.option('--vendor', default=None,
1655               help='[repository]: filter by vendor]')
1656 0 @click.option('--version', default='latest',
1657               help='[repository]: filter by version. Default: latest')
1658 0 @click.pass_context
1659 def nsd_create1(ctx, filename, overwrite, skip_charm_build, repo, vendor, version):
1660     """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED)
1661
1662     \b
1663     FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1664               If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1665               If FILENAME is an NF Package folder, it is built and then onboarded.
1666     """
1667 0     logger.debug("")
1668 0     nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, repo=repo, vendor=vendor,
1669                version=version)
1670
1671
1672 0 @cli_osm.command(name='nspkg-create', short_help='creates a new NSD/NSpkg')
1673 0 @click.argument('filename')
1674 0 @click.option('--overwrite', 'overwrite', default=None,  # hidden=True,
1675               help='Deprecated. Use override')
1676 0 @click.option('--override', 'overwrite', default=None,
1677               help='overrides fields in descriptor, format: '
1678                    '"key1.key2...=value[;key3...=value;...]"')
1679 0 @click.option('--skip-charm-build', default=False, is_flag=True,
1680               help='The charm will not be compiled, it is assumed to already exist')
1681 0 @click.option('--repo', default=None,
1682               help='[repository]: Repository name')
1683 0 @click.option('--vendor', default=None,
1684               help='[repository]: filter by vendor]')
1685 0 @click.option('--version', default='latest',
1686               help='[repository]: filter by version. Default: latest')
1687 0 @click.pass_context
1688 def nsd_pkg_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version):
1689     """onboards a new NSpkg
1690     \b
1691     FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1692               If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1693               If FILENAME is an NF Package folder, it is built and then onboarded.
1694     """
1695 0     logger.debug("")
1696 0     nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, repo=repo, vendor=vendor,
1697                version=version)
1698
1699
1700 0 def vnfd_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt,
1701                 repo, vendor, version):
1702 0     logger.debug("")
1703     # try:
1704 0     check_client_version(ctx.obj, ctx.command.name)
1705 0     if repo:
1706 0         filename = ctx.obj.osmrepo.get_pkg('vnf', filename, repo, vendor, version)
1707 0     ctx.obj.vnfd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build,
1708                         override_epa=override_epa, override_nonepa=override_nonepa,
1709                         override_paravirt=override_paravirt)
1710     # except ClientException as e:
1711     #     print(str(e))
1712     #     exit(1)
1713
1714
1715 0 @cli_osm.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg')
1716 0 @click.argument('filename')
1717 0 @click.option('--overwrite', 'overwrite', default=None,
1718               help='overwrite deprecated, use override')
1719 0 @click.option('--override', 'overwrite', default=None,
1720               help='overrides fields in descriptor, format: '
1721                    '"key1.key2...=value[;key3...=value;...]"')
1722 0 @click.option('--skip-charm-build', default=False, is_flag=True,
1723               help='The charm will not be compiled, it is assumed to already exist')
1724 0 @click.option('--override-epa', required=False, default=False, is_flag=True,
1725               help='adds guest-epa parameters to all VDU')
1726 0 @click.option('--override-nonepa', required=False, default=False, is_flag=True,
1727               help='removes all guest-epa parameters from all VDU')
1728 0 @click.option('--override-paravirt', required=False, default=False, is_flag=True,
1729               help='overrides all VDU interfaces to PARAVIRT')
1730 0 @click.option('--repo', default=None,
1731               help='[repository]: Repository name')
1732 0 @click.option('--vendor', default=None,
1733               help='[repository]: filter by vendor]')
1734 0 @click.option('--version', default='latest',
1735               help='[repository]: filter by version. Default: latest')
1736 0 @click.pass_context
1737 def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt,
1738                  repo,vendor, version):
1739     """creates a new VNFD/VNFpkg
1740     \b
1741     FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1742               If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1743               If FILENAME is an NF Package folder, it is built and then onboarded.
1744     """
1745 0     logger.debug("")
1746 0     vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build,
1747                 override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt,
1748                 repo=repo, vendor=vendor, version=version)
1749
1750
1751 0 @cli_osm.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg')
1752 0 @click.argument('filename')
1753 0 @click.option('--overwrite', 'overwrite', default=None,  # hidden=True,
1754               help='Deprecated. Use override')
1755 0 @click.option('--override', 'overwrite', default=None,
1756               help='overrides fields in descriptor, format: '
1757                    '"key1.key2...=value[;key3...=value;...]"')
1758 0 @click.option('--skip-charm-build', default=False, is_flag=True,
1759               help='The charm will not be compiled, it is assumed to already exist')
1760 0 @click.option('--override-epa', required=False, default=False, is_flag=True,
1761               help='adds guest-epa parameters to all VDU')
1762 0 @click.option('--override-nonepa', required=False, default=False, is_flag=True,
1763               help='removes all guest-epa parameters from all VDU')
1764 0 @click.option('--override-paravirt', required=False, default=False, is_flag=True,
1765               help='overrides all VDU interfaces to PARAVIRT')
1766 0 @click.option('--repo', default=None,
1767               help='[repository]: Repository name')
1768 0 @click.option('--vendor', default=None,
1769               help='[repository]: filter by vendor]')
1770 0 @click.option('--version', default='latest',
1771               help='[repository]: filter by version. Default: latest')
1772 0 @click.pass_context
1773 def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt,
1774                  repo, vendor, version):
1775     """creates a new VNFD/VNFpkg
1776     \b
1777     FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1778               If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1779               If FILENAME is an NF Package folder, it is built and then onboarded.
1780     """
1781 0     logger.debug("")
1782 0     vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build,
1783                 override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt,
1784                 repo=repo, vendor=vendor, version=version)
1785
1786 0 @cli_osm.command(name='nfpkg-create', short_help='creates a new NFpkg')
1787 0 @click.argument('filename')
1788 0 @click.option('--overwrite', 'overwrite', default=None,  # hidden=True,
1789               help='Deprecated. Use override')
1790 0 @click.option('--override', 'overwrite', default=None,
1791               help='overrides fields in descriptor, format: '
1792                    '"key1.key2...=value[;key3...=value;...]"')
1793 0 @click.option('--skip-charm-build', default=False, is_flag=True,
1794               help='The charm will not be compiled, it is assumed to already exist')
1795 0 @click.option('--override-epa', required=False, default=False, is_flag=True,
1796               help='adds guest-epa parameters to all VDU')
1797 0 @click.option('--override-nonepa', required=False, default=False, is_flag=True,
1798               help='removes all guest-epa parameters from all VDU')
1799 0 @click.option('--override-paravirt', required=False, default=False, is_flag=True,
1800               help='overrides all VDU interfaces to PARAVIRT')
1801 0 @click.option('--repo', default=None,
1802               help='[repository]: Repository name')
1803 0 @click.option('--vendor', default=None,
1804               help='[repository]: filter by vendor]')
1805 0 @click.option('--version', default='latest',
1806               help='[repository]: filter by version. Default: latest')
1807 0 @click.pass_context
1808 def nfpkg_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt,
1809                  repo, vendor, version):
1810     """creates a new NFpkg
1811
1812     \b
1813     FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder
1814               If FILENAME is a file (NF Package tar.gz or NF Descriptor YAML), it is onboarded.
1815               If FILENAME is an NF Package folder, it is built and then onboarded.
1816     """
1817 0     logger.debug("")
1818 0     vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build,
1819                 override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt,
1820                 repo=repo, vendor=vendor, version=version)
1821
1822
1823 0 @cli_osm.command(name='ns-create', short_help='creates a new Network Service instance')
1824 0 @click.option('--ns_name',
1825               prompt=True, help='name of the NS instance')
1826 0 @click.option('--nsd_name',
1827               prompt=True, help='name of the NS descriptor')
1828 0 @click.option('--vim_account',
1829               prompt=True, help='default VIM account id or name for the deployment')
1830 0 @click.option('--admin_status',
1831               default='ENABLED',
1832               help='administration status')
1833 0 @click.option('--ssh_keys',
1834               default=None,
1835               help='comma separated list of public key files to inject to vnfs')
1836 0 @click.option('--config',
1837               default=None,
1838               help='ns specific yaml configuration')
1839 0 @click.option('--config_file',
1840               default=None,
1841               help='ns specific yaml configuration file')
1842 0 @click.option('--wait',
1843               required=False,
1844               default=False,
1845               is_flag=True,
1846               help='do not return the control immediately, but keep it '
1847                    'until the operation is completed, or timeout')
1848 0 @click.pass_context
1849 def ns_create(ctx,
1850               nsd_name,
1851               ns_name,
1852               vim_account,
1853               admin_status,
1854               ssh_keys,
1855               config,
1856               config_file,
1857               wait):
1858     """creates a new NS instance"""
1859 0     logger.debug("")
1860     # try:
1861 0     if config_file:
1862 0         check_client_version(ctx.obj, '--config_file')
1863 0         if config:
1864 0             raise ClientException('"--config" option is incompatible with "--config_file" option')
1865 0         with open(config_file, 'r') as cf:
1866 0             config=cf.read()
1867 0     ctx.obj.ns.create(
1868         nsd_name,
1869         ns_name,
1870         config=config,
1871         ssh_keys=ssh_keys,
1872         account=vim_account,
1873         wait=wait)
1874     # except ClientException as e:
1875     #     print(str(e))
1876     #     exit(1)
1877
1878
1879 0 def nst_create(ctx, filename, overwrite):
1880 0     logger.debug("")
1881     # try:
1882 0     check_client_version(ctx.obj, ctx.command.name)
1883 0     ctx.obj.nst.create(filename, overwrite)
1884     # except ClientException as e:
1885     #     print(str(e))
1886     #     exit(1)
1887
1888
1889 0 @cli_osm.command(name='nst-create', short_help='creates a new Network Slice Template (NST)')
1890 0 @click.argument('filename')
1891 0 @click.option('--overwrite', 'overwrite', default=None,  # hidden=True,
1892               help='Deprecated. Use override')
1893 0 @click.option('--override', 'overwrite', default=None,
1894               help='overrides fields in descriptor, format: '
1895                    '"key1.key2...=value[;key3...=value;...]"')
1896 0 @click.pass_context
1897 def nst_create1(ctx, filename, overwrite):
1898     """creates a new Network Slice Template (NST)
1899
1900     FILENAME: NST package folder, NST yaml file or NSTpkg tar.gz file
1901     """
1902 0     logger.debug("")
1903 0     nst_create(ctx, filename, overwrite)
1904
1905
1906 0 @cli_osm.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)')
1907 0 @click.argument('filename')
1908 0 @click.option('--overwrite', 'overwrite', default=None,  # hidden=True,
1909               help='Deprecated. Use override')
1910 0 @click.option('--override', 'overwrite', default=None,
1911               help='overrides fields in descriptor, format: '
1912                    '"key1.key2...=value[;key3...=value;...]"')
1913 0 @click.pass_context
1914 def nst_create2(ctx, filename, overwrite):
1915     """creates a new Network Slice Template (NST)
1916
1917     FILENAME: NST yaml file or NSTpkg tar.gz file
1918     """
1919 0     logger.debug("")
1920 0     nst_create(ctx, filename, overwrite)
1921
1922
1923 0 def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1924     """creates a new Network Slice Instance (NSI)"""
1925 0     logger.debug("")
1926     # try:
1927 0     check_client_version(ctx.obj, ctx.command.name)
1928 0     if config_file:
1929 0         if config:
1930 0             raise ClientException('"--config" option is incompatible with "--config_file" option')
1931 0         with open(config_file, 'r') as cf:
1932 0             config=cf.read()
1933 0     ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys,
1934                        account=vim_account, wait=wait)
1935     # except ClientException as e:
1936     #     print(str(e))
1937     #     exit(1)
1938
1939
1940 0 @cli_osm.command(name='nsi-create', short_help='creates a new Network Slice Instance')
1941 0 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1942 0 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1943 0 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1944 0 @click.option('--ssh_keys', default=None,
1945               help='comma separated list of keys to inject to vnfs')
1946 0 @click.option('--config', default=None,
1947               help='Netslice specific yaml configuration:\n'
1948               'netslice_subnet: [\n'
1949                 'id: TEXT, vim_account: TEXT,\n'
1950                 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1951                 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n'
1952                 'additionalParamsForNsi: {param: value, ...}\n'
1953                 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n'
1954               '],\n'
1955               'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1956               )
1957 0 @click.option('--config_file',
1958               default=None,
1959               help='nsi specific yaml configuration file')
1960 0 @click.option('--wait',
1961               required=False,
1962               default=False,
1963               is_flag=True,
1964               help='do not return the control immediately, but keep it '
1965                    'until the operation is completed, or timeout')
1966 0 @click.pass_context
1967 def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1968     """creates a new Network Slice Instance (NSI)"""
1969 0     logger.debug("")
1970 0     nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
1971
1972
1973 0 @cli_osm.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance')
1974 0 @click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance')
1975 0 @click.option('--nst_name', prompt=True, help='name of the Network Slice Template')
1976 0 @click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment')
1977 0 @click.option('--ssh_keys', default=None,
1978               help='comma separated list of keys to inject to vnfs')
1979 0 @click.option('--config', default=None,
1980               help='Netslice specific yaml configuration:\n'
1981               'netslice_subnet: [\n'
1982                 'id: TEXT, vim_account: TEXT,\n'
1983                 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n'
1984                 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1985               '],\n'
1986               'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]'
1987               )
1988 0 @click.option('--config_file',
1989               default=None,
1990               help='nsi specific yaml configuration file')
1991 0 @click.option('--wait',
1992               required=False,
1993               default=False,
1994               is_flag=True,
1995               help='do not return the control immediately, but keep it '
1996                    'until the operation is completed, or timeout')
1997 0 @click.pass_context
1998 def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait):
1999     """creates a new Network Slice Instance (NSI)"""
2000 0     logger.debug("")
2001 0     nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait)
2002
2003
2004 0 @cli_osm.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog')
2005 0 @click.option('--name', help='name of the Physical Deployment Unit')
2006 0 @click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)')
2007 0 @click.option('--interface',
2008               help='interface(s) of the PDU: name=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
2009                    '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_NAME>]',
2010               multiple=True)
2011 0 @click.option('--description', help='human readable description')
2012 0 @click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True)
2013 0 @click.option('--descriptor_file', default=None,
2014               help='PDU descriptor file (as an alternative to using the other arguments')
2015 0 @click.pass_context
2016 def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file):
2017     """creates a new Physical Deployment Unit (PDU)"""
2018 0     logger.debug("")
2019     # try:
2020 0     check_client_version(ctx.obj, ctx.command.name)
2021 0     pdu = {}
2022 0     if not descriptor_file:
2023 0         if not name:
2024 0             raise ClientException('in absence of descriptor file, option "--name" is mandatory')
2025 0         if not pdu_type:
2026 0             raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory')
2027 0         if not interface:
2028 0             raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)')
2029 0         if not vim_account:
2030 0             raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)')
2031     else:
2032 0         with open(descriptor_file, 'r') as df:
2033 0             pdu = yaml.safe_load(df.read())
2034 0     if name: pdu["name"] = name
2035 0     if pdu_type: pdu["type"] = pdu_type
2036 0     if description: pdu["description"] = description
2037 0     if vim_account: pdu["vim_accounts"] = vim_account
2038 0     if interface:
2039 0         ifaces_list = []
2040 0         for iface in interface:
2041 0             new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]}
2042 0             new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true")
2043 0             ifaces_list.append(new_iface)
2044 0         pdu["interfaces"] = ifaces_list
2045 0     ctx.obj.pdu.create(pdu)
2046     # except ClientException as e:
2047     #     print(str(e))
2048     #     exit(1)
2049
2050
2051 ####################
2052 # UPDATE operations
2053 ####################
2054
2055 0 def nsd_update(ctx, name, content):
2056 0     logger.debug("")
2057     # try:
2058 0     check_client_version(ctx.obj, ctx.command.name)
2059 0     ctx.obj.nsd.update(name, content)
2060     # except ClientException as e:
2061     #     print(str(e))
2062     #     exit(1)
2063
2064
2065 0 @cli_osm.command(name='nsd-update', short_help='updates a NSD/NSpkg')
2066 0 @click.argument('name')
2067 0 @click.option('--content', default=None,
2068               help='filename with the NSD/NSpkg replacing the current one')
2069 0 @click.pass_context
2070 def nsd_update1(ctx, name, content):
2071     """updates a NSD/NSpkg
2072
2073     NAME: name or ID of the NSD/NSpkg
2074     """
2075 0     logger.debug("")
2076 0     nsd_update(ctx, name, content)
2077
2078
2079 0 @cli_osm.command(name='nspkg-update', short_help='updates a NSD/NSpkg')
2080 0 @click.argument('name')
2081 0 @click.option('--content', default=None,
2082               help='filename with the NSD/NSpkg replacing the current one')
2083 0 @click.pass_context
2084 def nsd_update2(ctx, name, content):
2085     """updates a NSD/NSpkg
2086
2087     NAME: name or ID of the NSD/NSpkg
2088     """
2089 0     logger.debug("")
2090 0     nsd_update(ctx, name, content)
2091
2092
2093 0 def vnfd_update(ctx, name, content):
2094 0     logger.debug("")
2095     # try:
2096 0     check_client_version(ctx.obj, ctx.command.name)
2097 0     ctx.obj.vnfd.update(name, content)
2098     # except ClientException as e:
2099     #     print(str(e))
2100     #     exit(1)
2101
2102
2103 0 @cli_osm.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg')
2104 0 @click.argument('name')
2105 0 @click.option('--content', default=None,
2106               help='filename with the VNFD/VNFpkg replacing the current one')
2107 0 @click.pass_context
2108 def vnfd_update1(ctx, name, content):
2109     """updates a VNFD/VNFpkg
2110
2111     NAME: name or ID of the VNFD/VNFpkg
2112     """
2113 0     logger.debug("")
2114 0     vnfd_update(ctx, name, content)
2115
2116
2117 0 @cli_osm.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg')
2118 0 @click.argument('name')
2119 0 @click.option('--content', default=None,
2120               help='filename with the VNFD/VNFpkg replacing the current one')
2121 0 @click.pass_context
2122 def vnfd_update2(ctx, name, content):
2123     """updates a VNFD/VNFpkg
2124
2125     NAME: VNFD yaml file or VNFpkg tar.gz file
2126     """
2127 0     logger.debug("")
2128 0     vnfd_update(ctx, name, content)
2129
2130
2131 0 @cli_osm.command(name='nfpkg-update', short_help='updates a NFpkg')
2132 0 @click.argument('name')
2133 0 @click.option('--content', default=None,
2134               help='filename with the NFpkg replacing the current one')
2135 0 @click.pass_context
2136 def nfpkg_update(ctx, name, content):
2137     """updates a NFpkg
2138
2139     NAME: NF Descriptor yaml file or NFpkg tar.gz file
2140     """
2141 0     logger.debug("")
2142 0     vnfd_update(ctx, name, content)
2143
2144
2145 0 def nst_update(ctx, name, content):
2146 0     logger.debug("")
2147     # try:
2148 0     check_client_version(ctx.obj, ctx.command.name)
2149 0     ctx.obj.nst.update(name, content)
2150     # except ClientException as e:
2151     #     print(str(e))
2152     #     exit(1)
2153
2154
2155 0 @cli_osm.command(name='nst-update', short_help='updates a Network Slice Template (NST)')
2156 0 @click.argument('name')
2157 0 @click.option('--content', default=None,
2158               help='filename with the NST/NSTpkg replacing the current one')
2159 0 @click.pass_context
2160 def nst_update1(ctx, name, content):
2161     """updates a Network Slice Template (NST)
2162
2163     NAME: name or ID of the NSD/NSpkg
2164     """
2165 0     logger.debug("")
2166 0     nst_update(ctx, name, content)
2167
2168
2169 0 @cli_osm.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)')
2170 0 @click.argument('name')
2171 0 @click.option('--content', default=None,
2172               help='filename with the NST/NSTpkg replacing the current one')
2173 0 @click.pass_context
2174 def nst_update2(ctx, name, content):
2175     """updates a Network Slice Template (NST)
2176
2177     NAME: name or ID of the NSD/NSpkg
2178     """
2179 0     logger.debug("")
2180 0     nst_update(ctx, name, content)
2181
2182
2183 ####################
2184 # DELETE operations
2185 ####################
2186
2187 0 def nsd_delete(ctx, name, force):
2188 0     logger.debug("")
2189     # try:
2190 0     if not force:
2191 0         ctx.obj.nsd.delete(name)
2192     else:
2193 0         check_client_version(ctx.obj, '--force')
2194 0         ctx.obj.nsd.delete(name, force)
2195     # except ClientException as e:
2196     #     print(str(e))
2197     #     exit(1)
2198
2199
2200 0 @cli_osm.command(name='nsd-delete', short_help='deletes a NSD/NSpkg')
2201 0 @click.argument('name')
2202 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2203 0 @click.pass_context
2204 def nsd_delete1(ctx, name, force):
2205     """deletes a NSD/NSpkg
2206
2207     NAME: name or ID of the NSD/NSpkg to be deleted
2208     """
2209 0     logger.debug("")
2210 0     nsd_delete(ctx, name, force)
2211
2212
2213 0 @cli_osm.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg')
2214 0 @click.argument('name')
2215 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2216 0 @click.pass_context
2217 def nsd_delete2(ctx, name, force):
2218     """deletes a NSD/NSpkg
2219
2220     NAME: name or ID of the NSD/NSpkg to be deleted
2221     """
2222 0     logger.debug("")
2223 0     nsd_delete(ctx, name, force)
2224
2225
2226 0 def vnfd_delete(ctx, name, force):
2227 0     logger.debug("")
2228     # try:
2229 0     if not force:
2230 0         ctx.obj.vnfd.delete(name)
2231     else:
2232 0         check_client_version(ctx.obj, '--force')
2233 0         ctx.obj.vnfd.delete(name, force)
2234     # except ClientException as e:
2235     #     print(str(e))
2236     #     exit(1)
2237
2238
2239 0 @cli_osm.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg')
2240 0 @click.argument('name')
2241 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2242 0 @click.pass_context
2243 def vnfd_delete1(ctx, name, force):
2244     """deletes a VNFD/VNFpkg
2245
2246     NAME: name or ID of the VNFD/VNFpkg to be deleted
2247     """
2248 0     logger.debug("")
2249 0     vnfd_delete(ctx, name, force)
2250
2251
2252 0 @cli_osm.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg')
2253 0 @click.argument('name')
2254 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2255 0 @click.pass_context
2256 def vnfd_delete2(ctx, name, force):
2257     """deletes a VNFD/VNFpkg
2258
2259     NAME: name or ID of the VNFD/VNFpkg to be deleted
2260     """
2261 0     logger.debug("")
2262 0     vnfd_delete(ctx, name, force)
2263
2264
2265 0 @cli_osm.command(name='nfpkg-delete', short_help='deletes a NFpkg')
2266 0 @click.argument('name')
2267 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2268 0 @click.pass_context
2269 def nfpkg_delete(ctx, name, force):
2270     """deletes a NFpkg
2271
2272     NAME: name or ID of the NFpkg to be deleted
2273     """
2274 0     logger.debug("")
2275 0     vnfd_delete(ctx, name, force)
2276
2277
2278 0 @cli_osm.command(name='ns-delete', short_help='deletes a NS instance')
2279 0 @click.argument('name')
2280 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2281 0 @click.option('--config', default=None,
2282               help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: "
2283                    "600, skip_terminate_primitives: True}'")
2284 0 @click.option('--wait',
2285               required=False,
2286               default=False,
2287               is_flag=True,
2288               help='do not return the control immediately, but keep it '
2289                    'until the operation is completed, or timeout')
2290 0 @click.pass_context
2291 def ns_delete(ctx, name, force, config, wait):
2292     """deletes a NS instance
2293
2294     NAME: name or ID of the NS instance to be deleted
2295     """
2296 0     logger.debug("")
2297     # try:
2298 0     if not force:
2299 0         ctx.obj.ns.delete(name, config=config, wait=wait)
2300     else:
2301 0         check_client_version(ctx.obj, '--force')
2302 0         ctx.obj.ns.delete(name, force, config=config, wait=wait)
2303     # except ClientException as e:
2304     #     print(str(e))
2305     #     exit(1)
2306
2307
2308 0 def nst_delete(ctx, name, force):
2309 0     logger.debug("")
2310     # try:
2311 0     check_client_version(ctx.obj, ctx.command.name)
2312 0     ctx.obj.nst.delete(name, force)
2313     # except ClientException as e:
2314     #     print(str(e))
2315     #     exit(1)
2316
2317
2318 0 @cli_osm.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)')
2319 0 @click.argument('name')
2320 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2321 0 @click.pass_context
2322 def nst_delete1(ctx, name, force):
2323     """deletes a Network Slice Template (NST)
2324
2325     NAME: name or ID of the NST/NSTpkg to be deleted
2326     """
2327 0     logger.debug("")
2328 0     nst_delete(ctx, name, force)
2329
2330
2331 0 @cli_osm.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)')
2332 0 @click.argument('name')
2333 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2334 0 @click.pass_context
2335 def nst_delete2(ctx, name, force):
2336     """deletes a Network Slice Template (NST)
2337
2338     NAME: name or ID of the NST/NSTpkg to be deleted
2339     """
2340 0     logger.debug("")
2341 0     nst_delete(ctx, name, force)
2342
2343
2344 0 def nsi_delete(ctx, name, force, wait):
2345 0     logger.debug("")
2346     # try:
2347 0     check_client_version(ctx.obj, ctx.command.name)
2348 0     ctx.obj.nsi.delete(name, force, wait=wait)
2349     # except ClientException as e:
2350     #     print(str(e))
2351     #     exit(1)
2352
2353
2354 0 @cli_osm.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)')
2355 0 @click.argument('name')
2356 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2357 0 @click.option('--wait',
2358               required=False,
2359               default=False,
2360               is_flag=True,
2361               help='do not return the control immediately, but keep it '
2362                    'until the operation is completed, or timeout')
2363 0 @click.pass_context
2364 def nsi_delete1(ctx, name, force, wait):
2365     """deletes a Network Slice Instance (NSI)
2366
2367     NAME: name or ID of the Network Slice instance to be deleted
2368     """
2369 0     logger.debug("")
2370 0     nsi_delete(ctx, name, force, wait=wait)
2371
2372
2373 0 @cli_osm.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)')
2374 0 @click.argument('name')
2375 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2376 0 @click.pass_context
2377 def nsi_delete2(ctx, name, force, wait):
2378     """deletes a Network Slice Instance (NSI)
2379
2380     NAME: name or ID of the Network Slice instance to be deleted
2381     """
2382 0     logger.debug("")
2383 0     nsi_delete(ctx, name, force, wait=wait)
2384
2385
2386 0 @cli_osm.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)')
2387 0 @click.argument('name')
2388 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2389 0 @click.pass_context
2390 def pdu_delete(ctx, name, force):
2391     """deletes a Physical Deployment Unit (PDU)
2392
2393     NAME: name or ID of the PDU to be deleted
2394     """
2395 0     logger.debug("")
2396     # try:
2397 0     check_client_version(ctx.obj, ctx.command.name)
2398 0     ctx.obj.pdu.delete(name, force)
2399     # except ClientException as e:
2400     #     print(str(e))
2401     #     exit(1)
2402
2403
2404 #################
2405 # VIM operations
2406 #################
2407
2408 0 @cli_osm.command(name='vim-create', short_help='creates a new VIM account')
2409 0 @click.option('--name',
2410               prompt=True,
2411               help='Name to create datacenter')
2412 0 @click.option('--user',
2413               prompt=True,
2414               help='VIM username')
2415 0 @click.option('--password',
2416               prompt=True,
2417               hide_input=True,
2418               confirmation_prompt=True,
2419               help='VIM password')
2420 0 @click.option('--auth_url',
2421               prompt=True,
2422               help='VIM url')
2423 0 @click.option('--tenant',
2424               prompt=True,
2425               help='VIM tenant name')
2426 0 @click.option('--config',
2427               default=None,
2428               help='VIM specific config parameters')
2429 0 @click.option('--account_type',
2430               default='openstack',
2431               help='VIM type')
2432 0 @click.option('--description',
2433               default=None,
2434               help='human readable description')
2435 0 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account')
2436 0 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2437 0 @click.option('--wait',
2438               required=False,
2439               default=False,
2440               is_flag=True,
2441               help='do not return the control immediately, but keep it '
2442                    'until the operation is completed, or timeout')
2443 0 @click.pass_context
2444 def vim_create(ctx,
2445                name,
2446                user,
2447                password,
2448                auth_url,
2449                tenant,
2450                config,
2451                account_type,
2452                description,
2453                sdn_controller,
2454                sdn_port_mapping,
2455                wait):
2456     """creates a new VIM account"""
2457 0     logger.debug("")
2458     # try:
2459 0     if sdn_controller:
2460 0         check_client_version(ctx.obj, '--sdn_controller')
2461 0     if sdn_port_mapping:
2462 0         check_client_version(ctx.obj, '--sdn_port_mapping')
2463 0     vim = {}
2464 0     vim['vim-username'] = user
2465 0     vim['vim-password'] = password
2466 0     vim['vim-url'] = auth_url
2467 0     vim['vim-tenant-name'] = tenant
2468 0     vim['vim-type'] = account_type
2469 0     vim['description'] = description
2470 0     vim['config'] = config
2471 0     if sdn_controller or sdn_port_mapping:
2472 0         ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
2473     else:
2474 0         ctx.obj.vim.create(name, vim, wait=wait)
2475     # except ClientException as e:
2476     #     print(str(e))
2477     #     exit(1)
2478
2479
2480 0 @cli_osm.command(name='vim-update', short_help='updates a VIM account')
2481 0 @click.argument('name')
2482 0 @click.option('--newname', help='New name for the VIM account')
2483 0 @click.option('--user', help='VIM username')
2484 0 @click.option('--password', help='VIM password')
2485 0 @click.option('--auth_url', help='VIM url')
2486 0 @click.option('--tenant', help='VIM tenant name')
2487 0 @click.option('--config', help='VIM specific config parameters')
2488 0 @click.option('--account_type', help='VIM type')
2489 0 @click.option('--description', help='human readable description')
2490 0 @click.option('--sdn_controller', default=None, help='Name or id of the SDN controller to be associated with this VIM'
2491                                                      'account. Use empty string to disassociate')
2492 0 @click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports")
2493 0 @click.option('--wait',
2494               required=False,
2495               default=False,
2496               is_flag=True,
2497               help='do not return the control immediately, but keep it '
2498                    'until the operation is completed, or timeout')
2499 0 @click.pass_context
2500 def vim_update(ctx,
2501                name,
2502                newname,
2503                user,
2504                password,
2505                auth_url,
2506                tenant,
2507                config,
2508                account_type,
2509                description,
2510                sdn_controller,
2511                sdn_port_mapping,
2512                wait):
2513     """updates a VIM account
2514
2515     NAME: name or ID of the VIM account
2516     """
2517 0     logger.debug("")
2518     # try:
2519 0     check_client_version(ctx.obj, ctx.command.name)
2520 0     vim = {}
2521 0     if newname: vim['name'] = newname
2522 0     if user: vim['vim_user'] = user
2523 0     if password: vim['vim_password'] = password
2524 0     if auth_url: vim['vim_url'] = auth_url
2525 0     if tenant: vim['vim-tenant-name'] = tenant
2526 0     if account_type: vim['vim_type'] = account_type
2527 0     if description: vim['description'] = description
2528 0     if config: vim['config'] = config
2529 0     ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait)
2530     # except ClientException as e:
2531     #     print(str(e))
2532     #     exit(1)
2533
2534
2535 0 @cli_osm.command(name='vim-delete', short_help='deletes a VIM account')
2536 0 @click.argument('name')
2537 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2538 0 @click.option('--wait',
2539               required=False,
2540               default=False,
2541               is_flag=True,
2542               help='do not return the control immediately, but keep it '
2543                    'until the operation is completed, or timeout')
2544 0 @click.pass_context
2545 def vim_delete(ctx, name, force, wait):
2546     """deletes a VIM account
2547
2548     NAME: name or ID of the VIM account to be deleted
2549     """
2550 0     logger.debug("")
2551     # try:
2552 0     if not force:
2553 0         ctx.obj.vim.delete(name, wait=wait)
2554     else:
2555 0         check_client_version(ctx.obj, '--force')
2556 0         ctx.obj.vim.delete(name, force, wait=wait)
2557     # except ClientException as e:
2558     #     print(str(e))
2559     #     exit(1)
2560
2561
2562 0 @cli_osm.command(name='vim-list', short_help='list all VIM accounts')
2563 #@click.option('--ro_update/--no_ro_update',
2564 #              default=False,
2565 #              help='update list from RO')
2566 0 @click.option('--filter', default=None, multiple=True,
2567               help='restricts the list to the VIM accounts matching the filter')
2568 0 @click.option('--long', is_flag=True,
2569               help='get more details of the NS (project, vim, deployment status, configuration status.')
2570 0 @click.pass_context
2571 def vim_list(ctx, filter, long):
2572     """list all VIM accounts"""
2573 0     logger.debug("")
2574 0     if filter:
2575 0         filter='&'.join(filter)
2576 0         check_client_version(ctx.obj, '--filter')
2577 #    if ro_update:
2578 #        check_client_version(ctx.obj, '--ro_update', 'v1')
2579 0     fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
2580 0     if fullclassname == 'osmclient.sol005.client.Client':
2581 0         resp = ctx.obj.vim.list(filter)
2582 #    else:
2583 #        resp = ctx.obj.vim.list(ro_update)
2584 0     if long:
2585 0         table = PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details'])
2586 0         project_list = ctx.obj.project.list()
2587     else:
2588 0         table = PrettyTable(['vim name', 'uuid', 'operational state'])
2589 0     for vim in resp:
2590 0         if long:
2591 0             if 'vim_password' in vim:
2592 0                 vim['vim_password']='********'
2593 0             logger.debug('VIM details: {}'.format(yaml.safe_dump(vim)))
2594 0             vim_state = vim['_admin'].get('operationalState', '-')
2595 0             error_details = 'N/A'
2596 0             if vim_state == 'ERROR':
2597 0                 error_details = vim['_admin'].get('detailed-status', 'Not found')
2598 0             project_id, project_name = get_project(project_list, vim)
2599             #project_info = '{} ({})'.format(project_name, project_id)
2600 0             project_info = project_name
2601 0             table.add_row([vim['name'], vim['uuid'], project_info,
2602                           vim_state, wrap_text(text=error_details, width=80)])
2603         else:
2604 0             table.add_row([vim['name'], vim['uuid'], vim['_admin'].get('operationalState', '-')])
2605 0     table.align = 'l'
2606 0     print(table)
2607
2608
2609 0 @cli_osm.command(name='vim-show', short_help='shows the details of a VIM account')
2610 0 @click.argument('name')
2611 0 @click.option('--filter', multiple=True,
2612               help='restricts the information to the fields in the filter')
2613 0 @click.pass_context
2614 def vim_show(ctx, name, filter):
2615     """shows the details of a VIM account
2616
2617     NAME: name or ID of the VIM account
2618     """
2619 0     logger.debug("")
2620     # try:
2621 0     resp = ctx.obj.vim.get(name)
2622 0     if 'vim_password' in resp:
2623 0         resp['vim_password']='********'
2624     # except ClientException as e:
2625     #     print(str(e))
2626     #     exit(1)
2627
2628 0     table = PrettyTable(['key', 'attribute'])
2629 0     for k, v in list(resp.items()):
2630 0         if not filter or k in filter:
2631 0             table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
2632 0     table.align = 'l'
2633 0     print(table)
2634
2635
2636 ####################
2637 # WIM operations
2638 ####################
2639
2640 0 @cli_osm.command(name='wim-create', short_help='creates a new WIM account')
2641 0 @click.option('--name',
2642               prompt=True,
2643               help='Name for the WIM account')
2644 0 @click.option('--user',
2645               help='WIM username')
2646 0 @click.option('--password',
2647               help='WIM password')
2648 0 @click.option('--url',
2649               prompt=True,
2650               help='WIM url')
2651 # @click.option('--tenant',
2652 #               help='wIM tenant name')
2653 0 @click.option('--config',
2654               default=None,
2655               help='WIM specific config parameters')
2656 0 @click.option('--wim_type',
2657               help='WIM type')
2658 0 @click.option('--description',
2659               default=None,
2660               help='human readable description')
2661 0 @click.option('--wim_port_mapping', default=None,
2662               help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2663                    "(WAN service endpoint id and info)")
2664 0 @click.option('--wait',
2665               required=False,
2666               default=False,
2667               is_flag=True,
2668               help='do not return the control immediately, but keep it '
2669                    'until the operation is completed, or timeout')
2670 0 @click.pass_context
2671 def wim_create(ctx,
2672                name,
2673                user,
2674                password,
2675                url,
2676                # tenant,
2677                config,
2678                wim_type,
2679                description,
2680                wim_port_mapping,
2681                wait):
2682     """creates a new WIM account"""
2683 0     logger.debug("")
2684     # try:
2685 0     check_client_version(ctx.obj, ctx.command.name)
2686     # if sdn_controller:
2687     #     check_client_version(ctx.obj, '--sdn_controller')
2688     # if sdn_port_mapping:
2689     #     check_client_version(ctx.obj, '--sdn_port_mapping')
2690 0     wim = {}
2691 0     if user: wim['user'] = user
2692 0     if password: wim['password'] = password
2693 0     if url: wim['wim_url'] = url
2694     # if tenant: wim['tenant'] = tenant
2695 0     wim['wim_type'] = wim_type
2696 0     if description: wim['description'] = description
2697 0     if config: wim['config'] = config
2698 0     ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait)
2699     # except ClientException as e:
2700     #     print(str(e))
2701     #     exit(1)
2702
2703
2704 0 @cli_osm.command(name='wim-update', short_help='updates a WIM account')
2705 0 @click.argument('name')
2706 0 @click.option('--newname', help='New name for the WIM account')
2707 0 @click.option('--user', help='WIM username')
2708 0 @click.option('--password', help='WIM password')
2709 0 @click.option('--url', help='WIM url')
2710 0 @click.option('--config', help='WIM specific config parameters')
2711 0 @click.option('--wim_type', help='WIM type')
2712 0 @click.option('--description', help='human readable description')
2713 0 @click.option('--wim_port_mapping', default=None,
2714               help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge "
2715                    "(WAN service endpoint id and info)")
2716 0 @click.option('--wait',
2717               required=False,
2718               default=False,
2719               is_flag=True,
2720               help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2721 0 @click.pass_context
2722 def wim_update(ctx,
2723                name,
2724                newname,
2725                user,
2726                password,
2727                url,
2728                config,
2729                wim_type,
2730                description,
2731                wim_port_mapping,
2732                wait):
2733     """updates a WIM account
2734
2735     NAME: name or ID of the WIM account
2736     """
2737 0     logger.debug("")
2738     # try:
2739 0     check_client_version(ctx.obj, ctx.command.name)
2740 0     wim = {}
2741 0     if newname: wim['name'] = newname
2742 0     if user: wim['user'] = user
2743 0     if password: wim['password'] = password
2744 0     if url: wim['url'] = url
2745     # if tenant: wim['tenant'] = tenant
2746 0     if wim_type: wim['wim_type'] = wim_type
2747 0     if description: wim['description'] = description
2748 0     if config: wim['config'] = config
2749 0     ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait)
2750     # except ClientException as e:
2751     #     print(str(e))
2752     #     exit(1)
2753
2754
2755 0 @cli_osm.command(name='wim-delete', short_help='deletes a WIM account')
2756 0 @click.argument('name')
2757 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2758 0 @click.option('--wait',
2759               required=False,
2760               default=False,
2761               is_flag=True,
2762               help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2763 0 @click.pass_context
2764 def wim_delete(ctx, name, force, wait):
2765     """deletes a WIM account
2766
2767     NAME: name or ID of the WIM account to be deleted
2768     """
2769 0     logger.debug("")
2770     # try:
2771 0     check_client_version(ctx.obj, ctx.command.name)
2772 0     ctx.obj.wim.delete(name, force, wait=wait)
2773     # except ClientException as e:
2774     #     print(str(e))
2775     #     exit(1)
2776
2777
2778 0 @cli_osm.command(name='wim-list', short_help='list all WIM accounts')
2779 0 @click.option('--filter', default=None, multiple=True,
2780               help='restricts the list to the WIM accounts matching the filter')
2781 0 @click.pass_context
2782 def wim_list(ctx, filter):
2783     """list all WIM accounts"""
2784 0     logger.debug("")
2785     # try:
2786 0     check_client_version(ctx.obj, ctx.command.name)
2787 0     if filter:
2788 0         filter='&'.join(filter)
2789 0     resp = ctx.obj.wim.list(filter)
2790 0     table = PrettyTable(['wim name', 'uuid'])
2791 0     for wim in resp:
2792 0         table.add_row([wim['name'], wim['uuid']])
2793 0     table.align = 'l'
2794 0     print(table)
2795     # except ClientException as e:
2796     #     print(str(e))
2797     #     exit(1)
2798
2799
2800 0 @cli_osm.command(name='wim-show', short_help='shows the details of a WIM account')
2801 0 @click.argument('name')
2802 0 @click.pass_context
2803 def wim_show(ctx, name):
2804     """shows the details of a WIM account
2805
2806     NAME: name or ID of the WIM account
2807     """
2808 0     logger.debug("")
2809     # try:
2810 0     check_client_version(ctx.obj, ctx.command.name)
2811 0     resp = ctx.obj.wim.get(name)
2812 0     if 'password' in resp:
2813 0         resp['wim_password']='********'
2814     # except ClientException as e:
2815     #     print(str(e))
2816     #     exit(1)
2817
2818 0     table = PrettyTable(['key', 'attribute'])
2819 0     for k, v in list(resp.items()):
2820 0         table.add_row([k, json.dumps(v, indent=2)])
2821 0     table.align = 'l'
2822 0     print(table)
2823
2824
2825 ####################
2826 # SDN controller operations
2827 ####################
2828
2829 0 @cli_osm.command(name='sdnc-create', short_help='creates a new SDN controller')
2830 0 @click.option('--name',
2831               prompt=True,
2832               help='Name to create sdn controller')
2833 0 @click.option('--type',
2834               prompt=True,
2835               help='SDN controller type')
2836 0 @click.option('--sdn_controller_version',  # hidden=True,
2837               help='Deprecated. Use --config {version: sdn_controller_version}')
2838 0 @click.option('--url',
2839               help='URL in format http[s]://HOST:IP/')
2840 0 @click.option('--ip_address',  # hidden=True,
2841               help='Deprecated. Use --url')
2842 0 @click.option('--port',  # hidden=True,
2843               help='Deprecated. Use --url')
2844 0 @click.option('--switch_dpid',  # hidden=True,
2845               help='Deprecated. Use --config {switch_id: DPID}')
2846 0 @click.option('--config',
2847               help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: '
2848              'Openflow Datapath ID), version: version}')
2849 0 @click.option('--user',
2850               help='SDN controller username')
2851 0 @click.option('--password',
2852               hide_input=True,
2853               confirmation_prompt=True,
2854               help='SDN controller password')
2855 0 @click.option('--description', default=None, help='human readable description')
2856 0 @click.option('--wait',
2857               required=False,
2858               default=False,
2859               is_flag=True,
2860               help="do not return the control immediately, but keep it until the operation is completed, or timeout")
2861 0 @click.pass_context
2862 def sdnc_create(ctx, **kwargs):
2863     """creates a new SDN controller"""
2864 0     logger.debug("")
2865 0     sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and
2866                      x not in ("wait", "ip_address", "port", "switch_dpid")}
2867 0     if kwargs.get("port"):
2868 0         print("option '--port' is deprecated, use '--url' instead")
2869 0         sdncontroller["port"] = int(kwargs["port"])
2870 0     if kwargs.get("ip_address"):
2871 0         print("option '--ip_address' is deprecated, use '--url' instead")
2872 0         sdncontroller["ip"] = kwargs["ip_address"]
2873 0     if kwargs.get("switch_dpid"):
2874 0         print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2875 0         sdncontroller["dpid"] = kwargs["switch_dpid"]
2876 0     if kwargs.get("sdn_controller_version"):
2877 0         print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'"
2878               " instead")
2879     # try:
2880 0     check_client_version(ctx.obj, ctx.command.name)
2881 0     ctx.obj.sdnc.create(kwargs["name"], sdncontroller, wait=kwargs["wait"])
2882     # except ClientException as e:
2883     #     print(str(e))
2884     #     exit(1)
2885
2886 0 @cli_osm.command(name='sdnc-update', short_help='updates an SDN controller')
2887 0 @click.argument('name')
2888 0 @click.option('--newname', help='New name for the SDN controller')
2889 0 @click.option('--description',  default=None, help='human readable description')
2890 0 @click.option('--type', help='SDN controller type')
2891 0 @click.option('--url', help='URL in format http[s]://HOST:IP/')
2892 0 @click.option('--config', help='Extra information for SDN in yaml format, as '
2893                                '{switch_id: identity used for the plugin (e.g. DPID: '
2894                                'Openflow Datapath ID), version: version}')
2895 0 @click.option('--user', help='SDN controller username')
2896 0 @click.option('--password', help='SDN controller password')
2897 0 @click.option('--ip_address', help='Deprecated. Use --url')  # hidden=True
2898 0 @click.option('--port', help='Deprecated. Use --url')  # hidden=True
2899 0 @click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}')  # hidden=True
2900 0 @click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}')  # hidden=True
2901 0 @click.option('--wait', required=False, default=False, is_flag=True,
2902               help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2903 0 @click.pass_context
2904 def sdnc_update(ctx, **kwargs):
2905     """updates an SDN controller
2906
2907     NAME: name or ID of the SDN controller
2908     """
2909 0     logger.debug("")
2910 0     sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and
2911                      x not in ("wait", "ip_address", "port", "switch_dpid", "new_name")}
2912 0     if kwargs.get("newname"):
2913 0         sdncontroller["name"] = kwargs["newname"]
2914 0     if kwargs.get("port"):
2915 0         print("option '--port' is deprecated, use '--url' instead")
2916 0         sdncontroller["port"] = int(kwargs["port"])
2917 0     if kwargs.get("ip_address"):
2918 0         print("option '--ip_address' is deprecated, use '--url' instead")
2919 0         sdncontroller["ip"] = kwargs["ip_address"]
2920 0     if kwargs.get("switch_dpid"):
2921 0         print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead")
2922 0         sdncontroller["dpid"] = kwargs["switch_dpid"]
2923 0     if kwargs.get("sdn_controller_version"):
2924 0         print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'"
2925               " instead")
2926
2927     # try:
2928 0     check_client_version(ctx.obj, ctx.command.name)
2929 0     ctx.obj.sdnc.update(kwargs["name"], sdncontroller, wait=kwargs["wait"])
2930     # except ClientException as e:
2931     #     print(str(e))
2932     #     exit(1)
2933
2934
2935 0 @cli_osm.command(name='sdnc-delete', short_help='deletes an SDN controller')
2936 0 @click.argument('name')
2937 0 @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
2938 0 @click.option('--wait', required=False, default=False, is_flag=True,
2939               help='do not return the control immediately, but keep it until the operation is completed, or timeout')
2940 0 @click.pass_context
2941 def sdnc_delete(ctx, name, force, wait):
2942     """deletes an SDN controller
2943
2944     NAME: name or ID of the SDN controller to be deleted
2945     """
2946 0     logger.debug("")
2947     # try:
2948 0     check_client_version(ctx.obj, ctx.command.name)
2949 0     ctx.obj.sdnc.delete(name, force, wait=wait)
2950     # except ClientException as e:
2951     #     print(str(e))
2952     #     exit(1)
2953
2954
2955 0 @cli_osm.command(name='sdnc-list', short_help='list all SDN controllers')
2956 0 @click.option('--filter', default=None, multiple=True,
2957               help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'")
2958 0 @click.pass_context
2959 def sdnc_list(ctx, filter):
2960     """list all SDN controllers"""
2961 0     logger.debug("")
2962     # try:
2963 0     check_client_version(ctx.obj, ctx.command.name)
2964 0     if filter:
2965 0         filter='&'.join(filter)
2966 0     resp = ctx.obj.sdnc.list(filter)
2967     # except ClientException as e:
2968     #     print(str(e))
2969     #     exit(1)
2970 0     table = PrettyTable(['sdnc name', 'id'])
2971 0     for sdnc in resp:
2972 0         table.add_row([sdnc['name'], sdnc['_id']])
2973 0     table.align = 'l'
2974 0     print(table)
2975
2976
2977 0 @cli_osm.command(name='sdnc-show', short_help='shows the details of an SDN controller')
2978 0 @click.argument('name')
2979 0 @click.pass_context
2980 def sdnc_show(ctx, name):
2981     """shows the details of an SDN controller
2982
2983     NAME: name or ID of the SDN controller
2984     """
2985 0     logger.debug("")
2986     # try:
2987 0     check_client_version(ctx.obj, ctx.command.name)
2988 0     resp = ctx.obj.sdnc.get(name)
2989     # except ClientException as e:
2990     #     print(str(e))
2991     #     exit(1)
2992
2993 0     table = PrettyTable(['key', 'attribute'])
2994 0     for k, v in list(resp.items()):
2995 0         table.add_row([k, json.dumps(v, indent=2)])
2996 0     table.align = 'l'
2997 0     print(table)
2998
2999
3000 ###########################
3001 # K8s cluster operations
3002 ###########################
3003
3004 0 @cli_osm.command(name='k8scluster-add', short_help='adds a K8s cluster to OSM')
3005 0 @click.argument('name')
3006 0 @click.option('--creds',
3007               prompt=True,
3008               help='credentials file, i.e. a valid `.kube/config` file')
3009 0 @click.option('--version',
3010               prompt=True,
3011               help='Kubernetes version')
3012 0 @click.option('--vim',
3013               prompt=True,
3014               help='VIM target, the VIM where the cluster resides')
3015 0 @click.option('--k8s-nets',
3016               prompt=True,
3017               help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
3018 0 @click.option('--description',
3019               default=None,
3020               help='human readable description')
3021 0 @click.option('--namespace',
3022               default='kube-system',
3023               help='namespace to be used for its operation, defaults to `kube-system`')
3024 0 @click.option('--cni',
3025               default=None,
3026               help='list of CNI plugins, in JSON inline format, used in the cluster')
3027 #@click.option('--skip-init',
3028 #              is_flag=True,
3029 #              help='If set, K8s cluster is assumed to be ready for its use with OSM')
3030 #@click.option('--wait',
3031 #              is_flag=True,
3032 #              help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3033 0 @click.pass_context
3034 def k8scluster_add(ctx,
3035                name,
3036                creds,
3037                version,
3038                vim,
3039                k8s_nets,
3040                description,
3041                namespace,
3042                cni):
3043     """adds a K8s cluster to OSM
3044
3045     NAME: name of the K8s cluster
3046     """
3047     # try:
3048 0     check_client_version(ctx.obj, ctx.command.name)
3049 0     cluster = {}
3050 0     cluster['name'] = name
3051 0     with open(creds, 'r') as cf:
3052 0         cluster['credentials'] = yaml.safe_load(cf.read())
3053 0     cluster['k8s_version'] = version
3054 0     cluster['vim_account'] = vim
3055 0     cluster['nets'] = yaml.safe_load(k8s_nets)
3056 0     if description:
3057 0         cluster['description'] = description
3058 0     if namespace: cluster['namespace'] = namespace
3059 0     if cni: cluster['cni'] = yaml.safe_load(cni)
3060 0     ctx.obj.k8scluster.create(name, cluster)
3061     # except ClientException as e:
3062     #     print(str(e))
3063     #     exit(1)
3064
3065
3066 0 @cli_osm.command(name='k8scluster-update', short_help='updates a K8s cluster')
3067 0 @click.argument('name')
3068 0 @click.option('--newname', help='New name for the K8s cluster')
3069 0 @click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file')
3070 0 @click.option('--version', help='Kubernetes version')
3071 0 @click.option('--vim', help='VIM target, the VIM where the cluster resides')
3072 0 @click.option('--k8s-nets', help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"')
3073 0 @click.option('--description', help='human readable description')
3074 0 @click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`')
3075 0 @click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster')
3076 0 @click.pass_context
3077 def k8scluster_update(ctx,
3078                name,
3079                newname,
3080                creds,
3081                version,
3082                vim,
3083                k8s_nets,
3084                description,
3085                namespace,
3086                cni):
3087     """updates a K8s cluster
3088
3089     NAME: name or ID of the K8s cluster
3090     """
3091     # try:
3092 0     check_client_version(ctx.obj, ctx.command.name)
3093 0     cluster = {}
3094 0     if newname: cluster['name'] = newname
3095 0     if creds:
3096 0         with open(creds, 'r') as cf:
3097 0             cluster['credentials'] = yaml.safe_load(cf.read())
3098 0     if version: cluster['k8s_version'] = version
3099 0     if vim: cluster['vim_account'] = vim
3100 0     if k8s_nets: cluster['nets'] = yaml.safe_load(k8s_nets)
3101 0     if description: cluster['description'] = description
3102 0     if namespace: cluster['namespace'] = namespace
3103 0     if cni: cluster['cni'] = yaml.safe_load(cni)
3104 0     ctx.obj.k8scluster.update(name, cluster)
3105     # except ClientException as e:
3106     #     print(str(e))
3107     #     exit(1)
3108
3109
3110 0 @cli_osm.command(name='k8scluster-delete', short_help='deletes a K8s cluster')
3111 0 @click.argument('name')
3112 0 @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)')
3113 #@click.option('--wait',
3114 #              is_flag=True,
3115 #              help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3116 0 @click.pass_context
3117 def k8scluster_delete(ctx, name, force):
3118     """deletes a K8s cluster
3119
3120     NAME: name or ID of the K8s cluster to be deleted
3121     """
3122     # try:
3123 0     check_client_version(ctx.obj, ctx.command.name)
3124 0     ctx.obj.k8scluster.delete(name, force=force)
3125     # except ClientException as e:
3126     #     print(str(e))
3127     #     exit(1)
3128
3129
3130 0 @cli_osm.command(name='k8scluster-list')
3131 0 @click.option('--filter', default=None, multiple=True,
3132               help='restricts the list to the K8s clusters matching the filter')
3133 0 @click.option('--literal', is_flag=True,
3134               help='print literally, no pretty table')
3135 0 @click.option('--long', is_flag=True, help='get more details')
3136 0 @click.pass_context
3137 def k8scluster_list(ctx, filter, literal, long):
3138     """list all K8s clusters"""
3139     # try:
3140 0     check_client_version(ctx.obj, ctx.command.name)
3141 0     if filter:
3142 0         filter='&'.join(filter)
3143 0     resp = ctx.obj.k8scluster.list(filter)
3144 0     if literal:
3145 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
3146 0         return
3147 0     if long:
3148 0         table = PrettyTable(['Name', 'Id', 'Project', 'Version', 'VIM', 'K8s-nets',
3149                              'Operational State', 'Op. state (details)', 'Description', 'Detailed status'])
3150 0         project_list = ctx.obj.project.list()
3151     else:
3152 0         table = PrettyTable(['Name', 'Id', 'VIM', 'Operational State', 'Op. state details'])
3153 0     try:
3154 0         vim_list = ctx.obj.vim.list()
3155 0     except:
3156 0         vim_list = []
3157 0     for cluster in resp:
3158 0         logger.debug('Cluster details: {}'.format(yaml.safe_dump(cluster)))
3159 0         vim_name = get_vim_name(vim_list, cluster['vim_account'])
3160         #vim_info = '{} ({})'.format(vim_name,cluster['vim_account'])
3161 0         vim_info = vim_name
3162 0         op_state_details = "Helm: {}\nJuju: {}".format(
3163                            cluster["_admin"].get("helm-chart", {}).get("operationalState", "-"),
3164                            cluster["_admin"].get("juju-bundle", {}).get("operationalState", "-"))
3165 0         if long:
3166 0             project_id, project_name = get_project(project_list, cluster)
3167             #project_info = '{} ({})'.format(project_name, project_id)
3168 0             project_info = project_name
3169 0             detailed_status = cluster["_admin"].get("detailed-status","-")
3170 0             table.add_row([cluster['name'], cluster['_id'], project_info,
3171                            cluster['k8s_version'], vim_info,
3172                            json.dumps(cluster['nets']), cluster["_admin"]["operationalState"],
3173                            op_state_details, trunc_text(cluster.get('description') or '', 40),
3174                            wrap_text(text=detailed_status, width=40)])
3175         else:
3176 0             table.add_row([cluster['name'], cluster['_id'], vim_info,
3177                            cluster["_admin"]["operationalState"], op_state_details])
3178 0     table.align = 'l'
3179 0     print(table)
3180     # except ClientException as e:
3181     #     print(str(e))
3182     #     exit(1)
3183
3184
3185 0 @cli_osm.command(name='k8scluster-show', short_help='shows the details of a K8s cluster')
3186 0 @click.argument('name')
3187 0 @click.option('--literal', is_flag=True,
3188               help='print literally, no pretty table')
3189 0 @click.pass_context
3190 def k8scluster_show(ctx, name, literal):
3191     """shows the details of a K8s cluster
3192
3193     NAME: name or ID of the K8s cluster
3194     """
3195     # try:
3196 0     resp = ctx.obj.k8scluster.get(name)
3197 0     if literal:
3198 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
3199 0         return
3200 0     table = PrettyTable(['key', 'attribute'])
3201 0     for k, v in list(resp.items()):
3202 0         table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)])
3203 0     table.align = 'l'
3204 0     print(table)
3205     # except ClientException as e:
3206     #     print(str(e))
3207     #     exit(1)
3208
3209
3210
3211 ###########################
3212 # Repo operations
3213 ###########################
3214
3215 0 @cli_osm.command(name='repo-add', short_help='adds a repo to OSM')
3216 0 @click.argument('name')
3217 0 @click.argument('uri')
3218 0 @click.option('--type',
3219               type=click.Choice(['helm-chart', 'juju-bundle', 'osm']),
3220               default='osm',
3221               help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)')
3222 0 @click.option('--description',
3223               default=None,
3224               help='human readable description')
3225 0 @click.option('--user',
3226               default=None,
3227               help='OSM repository: The username of the OSM repository')
3228 0 @click.option('--password',
3229               default=None,
3230               help='OSM repository: The password of the OSM repository')
3231 #@click.option('--wait',
3232 #              is_flag=True,
3233 #              help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3234 0 @click.pass_context
3235 def repo_add(ctx, **kwargs):
3236     """adds a repo to OSM
3237
3238     NAME: name of the repo
3239     URI: URI of the repo
3240     """
3241     # try:
3242 0     kwargs = {k: v for k, v in kwargs.items() if v is not None}
3243 0     repo = kwargs
3244 0     repo["url"] = repo.pop("uri")
3245 0     if repo["type"] in ['helm-chart', 'juju-bundle']:
3246 0         ctx.obj.repo.create(repo['name'], repo)
3247     else:
3248 0         ctx.obj.osmrepo.create(repo['name'], repo)
3249     # except ClientException as e:
3250     #     print(str(e))
3251     #     exit(1)
3252
3253
3254 0 @cli_osm.command(name='repo-update', short_help='updates a repo in OSM')
3255 0 @click.argument('name')
3256 0 @click.option('--newname', help='New name for the repo')
3257 0 @click.option('--uri', help='URI of the repo')
3258 0 @click.option('--description', help='human readable description')
3259 #@click.option('--wait',
3260 #              is_flag=True,
3261 #              help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3262 0 @click.pass_context
3263 def repo_update(ctx,
3264              name,
3265              newname,
3266              uri,
3267              description):
3268     """updates a repo in OSM
3269
3270     NAME: name of the repo
3271     """
3272     # try:
3273 0     check_client_version(ctx.obj, ctx.command.name)
3274 0     repo = {}
3275 0     if newname:
3276 0         repo['name'] = newname
3277 0     if uri:
3278 0         repo['uri'] = uri
3279 0     if description: repo['description'] = description
3280 0     try:
3281 0         ctx.obj.repo.update(name, repo)
3282 0     except NotFound:
3283 0         ctx.obj.osmrepo.update(name, repo)
3284
3285     # except ClientException as e:
3286     #     print(str(e))
3287     #     exit(1)
3288
3289
3290 0 @cli_osm.command(name='repo-index', short_help='Index a repository from a folder with artifacts')
3291 0 @click.option('--origin', default='.', help='origin path where the artifacts are located')
3292 0 @click.option('--destination', default='.', help='destination path where the index is deployed')
3293 0 @click.pass_context
3294 def repo_index(ctx, origin, destination):
3295     """Index a repository
3296
3297     NAME: name or ID of the repo to be deleted
3298     """
3299 0     check_client_version(ctx.obj, ctx.command.name)
3300 0     ctx.obj.osmrepo.repo_index(origin, destination)
3301
3302
3303 0 @cli_osm.command(name='repo-delete', short_help='deletes a repo')
3304 0 @click.argument('name')
3305 0 @click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)')
3306 #@click.option('--wait',
3307 #              is_flag=True,
3308 #              help='do not return the control immediately, but keep it until the operation is completed, or timeout')
3309 0 @click.pass_context
3310 def repo_delete(ctx, name, force):
3311     """deletes a repo
3312
3313     NAME: name or ID of the repo to be deleted
3314     """
3315 0     logger.debug("")
3316 0     try:
3317 0         ctx.obj.repo.delete(name, force=force)
3318 0     except NotFound:
3319 0         ctx.obj.osmrepo.delete(name, force=force)
3320     # except ClientException as e:
3321     #     print(str(e))
3322     #     exit(1)
3323
3324
3325 0 @cli_osm.command(name='repo-list')
3326 0 @click.option('--filter', default=None, multiple=True,
3327               help='restricts the list to the repos matching the filter')
3328 0 @click.option('--literal', is_flag=True,
3329               help='print literally, no pretty table')
3330 0 @click.pass_context
3331 def repo_list(ctx, filter, literal):
3332     """list all repos"""
3333     # try:
3334     # K8s Repositories
3335 0     check_client_version(ctx.obj, ctx.command.name)
3336 0     if filter:
3337 0         filter='&'.join(filter)
3338 0     resp = ctx.obj.repo.list(filter)
3339 0     resp += ctx.obj.osmrepo.list(filter)
3340 0     if literal:
3341 0         print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
3342 0         return
3343 0     table = PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description'])
3344 0     for repo in resp:
3345         #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
3346 0         table.add_row([repo['name'], repo['_id'], repo['type'], repo['url'], trunc_text(repo.get('description') or '',40)])
3347 0     table.align = 'l'
3348 0     print(table)
3349
3350     # except ClientException as e:
3351     #     print(str(e))
3352     #     exit(1)
3353
3354
3355 0 @cli_osm.command(name='repo-show', short_help='shows the details of a repo')
3356 0 @click.argument('name')
3357 0 @click.option('--literal', is_flag=True,
3358               help='print literally, no pretty table')
3359 0 @click.pass_context
3360 def repo_show(ctx, name, literal):
3361     """shows the details of a repo
3362
3363     NAME: name or ID of the repo
3364     """
3365 0     try:
3366 0         resp = ctx.obj.repo.get(name)
3367 0     except NotFound:
3368 0         resp = ctx.obj.osmrepo.get(name)
3369
3370 0     if literal:
3371 0         if resp:
3372 0             print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
3373 0         return
3374 0     table = PrettyTable(['key', 'attribute'])
3375 0     if resp:
3376 0         for k, v in list(resp.items()):
3377 0             table.add_row([k, json.dumps(v, indent=2)])
3378
3379 0     table.align = 'l'
3380 0     print(table)
3381     # except ClientException as e:
3382     #     print(str(e))
3383     #     exit(1)
3384
3385
3386
3387 ####################
3388 # Project mgmt operations
3389 ####################
3390
3391 0 @cli_osm.command(name='project-create', short_help='creates a new project')
3392 0 @click.argument('name')
3393 #@click.option('--description',
3394 #              default='no description',
3395 #              help='human readable description')
3396 0 @click.option('--domain-name', 'domain_name',
3397               default=None,
3398               help='assign to a domain')
3399 0 @click.option('--quotas', 'quotas', multiple=True, default=None,
3400               help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
3401                    "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos")
3402 0 @click.pass_context
3403 def project_create(ctx, name, domain_name, quotas):
3404     """Creates a new project
3405
3406     NAME: name of the project
3407     DOMAIN_NAME: optional domain name for the project when keystone authentication is used
3408     QUOTAS: set quotas for the project
3409     """
3410 0     logger.debug("")
3411 0     project = {'name': name}
3412 0     if domain_name:
3413 0         project['domain_name'] = domain_name
3414 0     quotas_dict = _process_project_quotas(quotas)
3415 0     if quotas_dict:
3416 0         project['quotas'] = quotas_dict
3417
3418     # try:
3419 0     check_client_version(ctx.obj, ctx.command.name)
3420 0     ctx.obj.project.create(name, project)
3421     # except ClientException as e:
3422     #     print(str(e))
3423     #     exit(1)
3424
3425
3426 0 def _process_project_quotas(quota_list):
3427 0     quotas_dict = {}
3428 0     if not quota_list:
3429 0         return quotas_dict
3430 0     try:
3431 0         for quota in quota_list:
3432 0             for single_quota in quota.split(","):
3433 0                 k, v = single_quota.split("=")
3434 0                 quotas_dict[k] = None if v in ('None', 'null', '') else int(v)
3435 0     except (ValueError, TypeError):
3436 0         raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null")
3437 0     return quotas_dict
3438
3439
3440 0 @cli_osm.command(name='project-delete', short_help='deletes a project')
3441 0 @click.argument('name')
3442 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3443 0 @click.pass_context
3444 def project_delete(ctx, name):
3445     """deletes a project
3446
3447     NAME: name or ID of the project to be deleted
3448     """
3449 0     logger.debug("")
3450     # try:
3451 0     check_client_version(ctx.obj, ctx.command.name)
3452 0     ctx.obj.project.delete(name)
3453     # except ClientException as e:
3454     #     print(str(e))
3455     #     exit(1)
3456
3457
3458 0 @cli_osm.command(name='project-list', short_help='list all projects')
3459 0 @click.option('--filter', default=None, multiple=True,
3460               help='restricts the list to the projects matching the filter')
3461 0 @click.pass_context
3462 def project_list(ctx, filter):
3463     """list all projects"""
3464 0     logger.debug("")
3465     # try:
3466 0     check_client_version(ctx.obj, ctx.command.name)
3467 0     if filter:
3468 0         filter='&'.join(filter)
3469 0     resp = ctx.obj.project.list(filter)
3470     # except ClientException as e:
3471     #     print(str(e))
3472     #     exit(1)
3473 0     table = PrettyTable(['name', 'id'])
3474 0     for proj in resp:
3475 0         table.add_row([proj['name'], proj['_id']])
3476 0     table.align = 'l'
3477 0     print(table)
3478
3479
3480 0 @cli_osm.command(name='project-show', short_help='shows the details of a project')
3481 0 @click.argument('name')
3482 0 @click.pass_context
3483 def project_show(ctx, name):
3484     """shows the details of a project
3485
3486     NAME: name or ID of the project
3487     """
3488 0     logger.debug("")
3489     # try:
3490 0     check_client_version(ctx.obj, ctx.command.name)
3491 0     resp = ctx.obj.project.get(name)
3492     # except ClientException as e:
3493     #     print(str(e))
3494     #     exit(1)
3495
3496 0     table = PrettyTable(['key', 'attribute'])
3497 0     for k, v in resp.items():
3498 0         table.add_row([k, json.dumps(v, indent=2)])
3499 0     table.align = 'l'
3500 0     print(table)
3501
3502
3503 0 @cli_osm.command(name='project-update', short_help='updates a project (only the name can be updated)')
3504 0 @click.argument('project')
3505 0 @click.option('--name', default=None,
3506               help='new name for the project')
3507 0 @click.option('--quotas', 'quotas', multiple=True, default=None,
3508               help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
3509                    "(use empty to reset quota to default")
3510 0 @click.pass_context
3511 def project_update(ctx, project, name, quotas):
3512     """
3513     Update a project name
3514
3515     :param ctx:
3516     :param project: id or name of the project to modify
3517     :param name:  new name for the project
3518     :param quotas:  change quotas of the project
3519     :return:
3520     """
3521 0     logger.debug("")
3522 0     project_changes = {}
3523 0     if name:
3524 0         project_changes['name'] = name
3525 0     quotas_dict = _process_project_quotas(quotas)
3526 0     if quotas_dict:
3527 0         project_changes['quotas'] = quotas_dict
3528
3529     # try:
3530 0     check_client_version(ctx.obj, ctx.command.name)
3531 0     ctx.obj.project.update(project, project_changes)
3532     # except ClientException as e:
3533     #     print(str(e))
3534
3535
3536 ####################
3537 # User mgmt operations
3538 ####################
3539
3540 0 @cli_osm.command(name='user-create', short_help='creates a new user')
3541 0 @click.argument('username')
3542 0 @click.option('--password',
3543               prompt=True,
3544               hide_input=True,
3545               confirmation_prompt=True,
3546               help='user password')
3547 0 @click.option('--projects',
3548               # prompt="Comma separate list of projects",
3549               multiple=True,
3550               callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value,
3551               help='list of project ids that the user belongs to')
3552 0 @click.option('--project-role-mappings', 'project_role_mappings',
3553               default=None, multiple=True,
3554               help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3555 0 @click.option('--domain-name', 'domain_name',
3556               default=None,
3557               help='assign to a domain')
3558 0 @click.pass_context
3559 def user_create(ctx, username, password, projects, project_role_mappings, domain_name):
3560     """Creates a new user
3561
3562     \b
3563     USERNAME: name of the user
3564     PASSWORD: password of the user
3565     PROJECTS: projects assigned to user (internal only)
3566     PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
3567     DOMAIN_NAME: optional domain name for the user when keystone authentication is used
3568     """
3569 0     logger.debug("")
3570 0     user = {}
3571 0     user['username'] = username
3572 0     user['password'] = password
3573 0     user['projects'] = projects
3574 0     user['project_role_mappings'] = project_role_mappings
3575 0     if domain_name:
3576 0         user['domain_name'] = domain_name
3577
3578     # try:
3579 0     check_client_version(ctx.obj, ctx.command.name)
3580 0     ctx.obj.user.create(username, user)
3581     # except ClientException as e:
3582     #     print(str(e))
3583     #     exit(1)
3584
3585
3586 0 @cli_osm.command(name='user-update', short_help='updates user information')
3587 0 @click.argument('username')
3588 0 @click.option('--password',
3589               # prompt=True,
3590               # hide_input=True,
3591               # confirmation_prompt=True,
3592               help='user password')
3593 0 @click.option('--set-username', 'set_username',
3594               default=None,
3595               help='change username')
3596 0 @click.option('--set-project', 'set_project',
3597               default=None, multiple=True,
3598               help="create/replace the roles for this project: 'project,role1[,role2,...]'")
3599 0 @click.option('--remove-project', 'remove_project',
3600               default=None, multiple=True,
3601               help="removes project from user: 'project'")
3602 0 @click.option('--add-project-role', 'add_project_role',
3603               default=None, multiple=True,
3604               help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3605 0 @click.option('--remove-project-role', 'remove_project_role',
3606               default=None, multiple=True,
3607               help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'")
3608 0 @click.pass_context
3609 def user_update(ctx, username, password, set_username, set_project, remove_project,
3610                 add_project_role, remove_project_role):
3611     """Update a user information
3612
3613     \b
3614     USERNAME: name of the user
3615     PASSWORD: new password
3616     SET_USERNAME: new username
3617     SET_PROJECT: creating mappings for project/role(s)
3618     REMOVE_PROJECT: deleting mappings for project/role(s)
3619     ADD_PROJECT_ROLE: adding mappings for project/role(s)
3620     REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
3621     """
3622 0     logger.debug("")
3623 0     user = {}
3624 0     user['password'] = password
3625 0     user['username'] = set_username
3626 0     user['set-project'] = set_project
3627 0     user['remove-project'] = remove_project
3628 0     user['add-project-role'] = add_project_role
3629 0     user['remove-project-role'] = remove_project_role
3630     
3631     # try:
3632 0     check_client_version(ctx.obj, ctx.command.name)
3633 0     ctx.obj.user.update(username, user)
3634     # except ClientException as e:
3635     #     print(str(e))
3636     #     exit(1)
3637
3638
3639 0 @cli_osm.command(name='user-delete', short_help='deletes a user')
3640 0 @click.argument('name')
3641 #@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
3642 0 @click.pass_context
3643 def user_delete(ctx, name):
3644     """deletes a user
3645
3646     \b
3647     NAME: name or ID of the user to be deleted
3648     """
3649 0     logger.debug("")
3650     # try:
3651 0     check_client_version(ctx.obj, ctx.command.name)
3652 0     ctx.obj.user.delete(name)
3653     # except ClientException as e:
3654     #     print(str(e))
3655     #     exit(1)
3656
3657
3658 0 @cli_osm.command(name='user-list', short_help='list all users')
3659 0 @click.option('--filter', default=None, multiple=True,
3660               help='restricts the list to the users matching the filter')
3661 0 @click.pass_context
3662 def user_list(ctx, filter):
3663     """list all users"""
3664     # try:
3665 0     check_client_version(ctx.obj, ctx.command.name)
3666 0     if filter:
3667 0         filter='&'.join(filter)
3668 0     resp = ctx.obj.user.list(filter)
3669     # except ClientException as e:
3670     #     print(str(e))
3671     #     exit(1)
3672 0     table = PrettyTable(['name', 'id'])
3673 0     for user in resp:
3674 0         table.add_row([user['username'], user['_id']])
3675 0     table.align = 'l'
3676 0     print(table)
3677
3678
3679 0 @cli_osm.command(name='user-show', short_help='shows the details of a user')
3680 0 @click.argument('name')
3681 0 @click.pass_context
3682 def user_show(ctx, name):
3683     """shows the details of a user
3684
3685     NAME: name or ID of the user
3686     """
3687 0     logger.debug("")
3688     # try:
3689 0     check_client_version(ctx.obj, ctx.command.name)
3690 0     resp = ctx.obj.user.get(name)
3691 0     if 'password' in resp:
3692 0         resp['password']='********'
3693     # except ClientException as e:
3694     #     print(str(e))
3695     #     exit(1)
3696
3697 0     table = PrettyTable(['key', 'attribute'])
3698 0     for k, v in resp.items():
3699 0         table.add_row([k, json.dumps(v, indent=2)])
3700 0     table.align = 'l'
3701 0     print(table)
3702
3703
3704 ####################
3705 # Fault Management operations
3706 ####################
3707
3708 0 @cli_osm.command(name='ns-alarm-create')
3709 0 @click.argument('name')
3710 0 @click.option('--ns', prompt=True, help='NS instance id or name')
3711 0 @click.option('--vnf', prompt=True,
3712               help='VNF name (VNF member index as declared in the NSD)')
3713 0 @click.option('--vdu', prompt=True,
3714               help='VDU name (VDU name as declared in the VNFD)')
3715 0 @click.option('--metric', prompt=True,
3716               help='Name of the metric (e.g. cpu_utilization)')
3717 0 @click.option('--severity', default='WARNING',
3718               help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)')
3719 0 @click.option('--threshold_value', prompt=True,
3720               help='threshold value that, when crossed, an alarm is triggered')
3721 0 @click.option('--threshold_operator', prompt=True,
3722               help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)')
3723 0 @click.option('--statistic', default='AVERAGE',
3724               help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)')
3725 0 @click.pass_context
3726 def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity,
3727                     threshold_value, threshold_operator, statistic):
3728     """creates a new alarm for a NS instance"""
3729     # TODO: Check how to validate threshold_value.
3730     # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)?
3731 0     logger.debug("")
3732     # try:
3733 0     ns_instance = ctx.obj.ns.get(ns)
3734 0     alarm = {}
3735 0     alarm['alarm_name'] = name
3736 0     alarm['ns_id'] = ns_instance['_id']
3737 0     alarm['correlation_id'] = ns_instance['_id']
3738 0     alarm['vnf_member_index'] = vnf
3739 0     alarm['vdu_name'] = vdu
3740 0     alarm['metric_name'] = metric
3741 0     alarm['severity'] = severity
3742 0     alarm['threshold_value'] = int(threshold_value)
3743 0     alarm['operation'] = threshold_operator
3744 0     alarm['statistic'] = statistic
3745 0     check_client_version(ctx.obj, ctx.command.name)
3746 0     ctx.obj.ns.create_alarm(alarm)
3747     # except ClientException as e:
3748     #     print(str(e))
3749     #     exit(1)
3750
3751
3752 #@cli_osm.command(name='ns-alarm-delete')
3753 #@click.argument('name')
3754 #@click.pass_context
3755 #def ns_alarm_delete(ctx, name):
3756 #    """deletes an alarm
3757 #
3758 #    NAME: name of the alarm to be deleted
3759 #    """
3760 #    try:
3761 #        check_client_version(ctx.obj, ctx.command.name)
3762 #        ctx.obj.ns.delete_alarm(name)
3763 #    except ClientException as e:
3764 #        print(str(e))
3765 #        exit(1)
3766
3767
3768 ####################
3769 # Performance Management operations
3770 ####################
3771
3772 0 @cli_osm.command(name='ns-metric-export', short_help='exports a metric to the internal OSM bus, which can be read by other apps')
3773 0 @click.option('--ns', prompt=True, help='NS instance id or name')
3774 0 @click.option('--vnf', prompt=True,
3775               help='VNF name (VNF member index as declared in the NSD)')
3776 0 @click.option('--vdu', prompt=True,
3777               help='VDU name (VDU name as declared in the VNFD)')
3778 0 @click.option('--metric', prompt=True,
3779               help='name of the metric (e.g. cpu_utilization)')
3780 #@click.option('--period', default='1w',
3781 #              help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)')
3782 0 @click.option('--interval', help='periodic interval (seconds) to export metrics continuously')
3783 0 @click.pass_context
3784 def ns_metric_export(ctx, ns, vnf, vdu, metric, interval):
3785     """exports a metric to the internal OSM bus, which can be read by other apps"""
3786     # TODO: Check how to validate interval.
3787     # Should it be an integer (seconds), or should a suffix (s,m,h,d,w) also be permitted?
3788 0     logger.debug("")
3789     # try:
3790 0     ns_instance = ctx.obj.ns.get(ns)
3791 0     metric_data = {}
3792 0     metric_data['ns_id'] = ns_instance['_id']
3793 0     metric_data['correlation_id'] = ns_instance['_id']
3794 0     metric_data['vnf_member_index'] = vnf
3795 0     metric_data['vdu_name'] = vdu
3796 0     metric_data['metric_name'] = metric
3797 0     metric_data['collection_unit'] = 'WEEK'
3798 0     metric_data['collection_period'] = 1
3799 0     check_client_version(ctx.obj, ctx.command.name)
3800 0     if not interval:
3801 0         print('{}'.format(ctx.obj.ns.export_metric(metric_data)))
3802     else:
3803 0         i = 1
3804 0         while True:
3805 0             print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i))
3806 0             time.sleep(int(interval))
3807 0             i+=1
3808     # except ClientException as e:
3809     #     print(str(e))
3810     #     exit(1)
3811
3812
3813 ####################
3814 # Other operations
3815 ####################
3816
3817 0 @cli_osm.command(name='version', short_help='shows client and server versions')
3818 0 @click.pass_context
3819 def get_version(ctx):
3820     """shows client and server versions"""
3821     # try:
3822 0     check_client_version(ctx.obj, "version")
3823 0     print ("Server version: {}".format(ctx.obj.get_version()))
3824 0     print ("Client version: {}".format(pkg_resources.get_distribution("osmclient").version))
3825     # except ClientException as e:
3826     #     print(str(e))
3827     #     exit(1)
3828
3829 0 @cli_osm.command(name='upload-package', short_help='uploads a VNF package or NS package')
3830 0 @click.argument('filename')
3831 0 @click.option('--skip-charm-build', default=False, is_flag=True,
3832               help='the charm will not be compiled, it is assumed to already exist')
3833 0 @click.pass_context
3834 def upload_package(ctx, filename, skip_charm_build):
3835     """uploads a vnf package or ns package
3836
3837     filename: vnf or ns package folder, or vnf or ns package file (tar.gz)
3838     """
3839 0     logger.debug("")
3840     # try:
3841 0     ctx.obj.package.upload(filename, skip_charm_build=skip_charm_build)
3842 0     fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
3843 0     if fullclassname != 'osmclient.sol005.client.Client':
3844 0         ctx.obj.package.wait_for_upload(filename)
3845     # except ClientException as e:
3846     #     print(str(e))
3847     #     exit(1)
3848
3849
3850 #@cli_osm.command(name='ns-scaling-show')
3851 #@click.argument('ns_name')
3852 #@click.pass_context
3853 #def show_ns_scaling(ctx, ns_name):
3854 #    """shows the status of a NS scaling operation
3855 #
3856 #    NS_NAME: name of the NS instance being scaled
3857 #    """
3858 #    try:
3859 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
3860 #        resp = ctx.obj.ns.list()
3861 #    except ClientException as e:
3862 #        print(str(e))
3863 #        exit(1)
3864 #
3865 #    table = PrettyTable(
3866 #        ['group-name',
3867 #         'instance-id',
3868 #         'operational status',
3869 #         'create-time',
3870 #         'vnfr ids'])
3871 #
3872 #    for ns in resp:
3873 #        if ns_name == ns['name']:
3874 #            nsopdata = ctx.obj.ns.get_opdata(ns['id'])
3875 #            scaling_records = nsopdata['nsr:nsr']['scaling-group-record']
3876 #            for record in scaling_records:
3877 #                if 'instance' in record:
3878 #                    instances = record['instance']
3879 #                    for inst in instances:
3880 #                        table.add_row(
3881 #                            [record['scaling-group-name-ref'],
3882 #                             inst['instance-id'],
3883 #                                inst['op-status'],
3884 #                                time.strftime('%Y-%m-%d %H:%M:%S',
3885 #                                              time.localtime(
3886 #                                                  inst['create-time'])),
3887 #                                inst['vnfrs']])
3888 #    table.align = 'l'
3889 #    print(table)
3890
3891
3892 #@cli_osm.command(name='ns-scale')
3893 #@click.argument('ns_name')
3894 #@click.option('--ns_scale_group', prompt=True)
3895 #@click.option('--index', prompt=True)
3896 #@click.option('--wait',
3897 #              required=False,
3898 #              default=False,
3899 #              is_flag=True,
3900 #              help='do not return the control immediately, but keep it \
3901 #              until the operation is completed, or timeout')
3902 #@click.pass_context
3903 #def ns_scale(ctx, ns_name, ns_scale_group, index, wait):
3904 #    """scales NS
3905 #
3906 #    NS_NAME: name of the NS instance to be scaled
3907 #    """
3908 #    try:
3909 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
3910 #        ctx.obj.ns.scale(ns_name, ns_scale_group, index, wait=wait)
3911 #    except ClientException as e:
3912 #        print(str(e))
3913 #        exit(1)
3914
3915
3916 #@cli_osm.command(name='config-agent-list')
3917 #@click.pass_context
3918 #def config_agent_list(ctx):
3919 #    """list config agents"""
3920 #    try:
3921 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
3922 #    except ClientException as e:
3923 #        print(str(e))
3924 #        exit(1)
3925 #    table = PrettyTable(['name', 'account-type', 'details'])
3926 #    for account in ctx.obj.vca.list():
3927 #        table.add_row(
3928 #            [account['name'],
3929 #             account['account-type'],
3930 #             account['juju']])
3931 #    table.align = 'l'
3932 #    print(table)
3933
3934
3935 #@cli_osm.command(name='config-agent-delete')
3936 #@click.argument('name')
3937 #@click.pass_context
3938 #def config_agent_delete(ctx, name):
3939 #    """deletes a config agent
3940 #
3941 #    NAME: name of the config agent to be deleted
3942 #    """
3943 #    try:
3944 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
3945 #        ctx.obj.vca.delete(name)
3946 #    except ClientException as e:
3947 #        print(str(e))
3948 #        exit(1)
3949
3950
3951 #@cli_osm.command(name='config-agent-add')
3952 #@click.option('--name',
3953 #              prompt=True)
3954 #@click.option('--account_type',
3955 #              prompt=True)
3956 #@click.option('--server',
3957 #              prompt=True)
3958 #@click.option('--user',
3959 #              prompt=True)
3960 #@click.option('--secret',
3961 #              prompt=True,
3962 #              hide_input=True,
3963 #              confirmation_prompt=True)
3964 #@click.pass_context
3965 #def config_agent_add(ctx, name, account_type, server, user, secret):
3966 #    """adds a config agent"""
3967 #    try:
3968 #        check_client_version(ctx.obj, ctx.command.name, 'v1')
3969 #        ctx.obj.vca.create(name, account_type, server, user, secret)
3970 #    except ClientException as e:
3971 #        print(str(e))
3972 #        exit(1)
3973
3974
3975 #@cli_osm.command(name='ro-dump')
3976 #@click.pass_context
3977 #def ro_dump(ctx):
3978 #    """shows RO agent information"""
3979 #    check_client_version(ctx.obj, ctx.command.name, 'v1')
3980 #    resp = ctx.obj.vim.get_resource_orchestrator()
3981 #    table = PrettyTable(['key', 'attribute'])
3982 #    for k, v in list(resp.items()):
3983 #        table.add_row([k, json.dumps(v, indent=2)])
3984 #    table.align = 'l'
3985 #    print(table)
3986
3987
3988 #@cli_osm.command(name='vcs-list')
3989 #@click.pass_context
3990 #def vcs_list(ctx):
3991 #    check_client_version(ctx.obj, ctx.command.name, 'v1')
3992 #    resp = ctx.obj.utils.get_vcs_info()
3993 #    table = PrettyTable(['component name', 'state'])
3994 #    for component in resp:
3995 #        table.add_row([component['component_name'], component['state']])
3996 #    table.align = 'l'
3997 #    print(table)
3998
3999
4000 0 @cli_osm.command(name='ns-action', short_help='executes an action/primitive over a NS instance')
4001 0 @click.argument('ns_name')
4002 0 @click.option('--vnf_name', default=None, help='member-vnf-index if the target is a vnf instead of a ns)')
4003 0 @click.option('--kdu_name', default=None, help='kdu-name if the target is a kdu)')
4004 0 @click.option('--vdu_id', default=None, help='vdu-id if the target is a vdu')
4005 0 @click.option('--vdu_count', default=None, type=int, help='number of vdu instance of this vdu_id')
4006 0 @click.option('--action_name', prompt=True, help='action name')
4007 0 @click.option('--params', default=None, help='action params in YAML/JSON inline string')
4008 0 @click.option('--params_file', default=None, help='YAML/JSON file with action params')
4009 0 @click.option('--timeout', required=False, default=None, type=int, help='timeout in seconds')
4010 0 @click.option('--wait',
4011               required=False,
4012               default=False,
4013               is_flag=True,
4014               help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4015 0 @click.pass_context
4016 def ns_action(ctx,
4017               ns_name,
4018               vnf_name,
4019               kdu_name,
4020               vdu_id,
4021               vdu_count,
4022               action_name,
4023               params,
4024               params_file,
4025               timeout,
4026               wait):
4027     """executes an action/primitive over a NS instance
4028
4029     NS_NAME: name or ID of the NS instance
4030     """
4031 0     logger.debug("")
4032     # try:
4033 0     check_client_version(ctx.obj, ctx.command.name)
4034 0     op_data = {}
4035 0     if vnf_name:
4036 0         op_data['member_vnf_index'] = vnf_name
4037 0     if kdu_name:
4038 0         op_data['kdu_name'] = kdu_name
4039 0     if vdu_id:
4040 0         op_data['vdu_id'] = vdu_id
4041 0     if vdu_count is not None:
4042 0         op_data['vdu_count_index'] = vdu_count
4043 0     if timeout:
4044 0         op_data['timeout_ns_action'] = timeout
4045 0     op_data['primitive'] = action_name
4046 0     if params_file:
4047 0         with open(params_file, 'r') as pf:
4048 0             params = pf.read()
4049 0     if params:
4050 0         op_data['primitive_params'] = yaml.safe_load(params)
4051     else:
4052 0         op_data['primitive_params'] = {}
4053 0     print(ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait))
4054
4055     # except ClientException as e:
4056     #     print(str(e))
4057     #     exit(1)
4058
4059
4060 0 @cli_osm.command(name='vnf-scale', short_help='executes a VNF scale (adding/removing VDUs)')
4061 0 @click.argument('ns_name')
4062 0 @click.argument('vnf_name')
4063 0 @click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use")
4064 0 @click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation")
4065 0 @click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)")
4066 0 @click.option('--timeout', required=False, default=None, type=int, help='timeout in seconds')
4067 0 @click.option('--wait', required=False, default=False, is_flag=True,
4068               help='do not return the control immediately, but keep it until the operation is completed, or timeout')
4069 0 @click.pass_context
4070 def vnf_scale(ctx,
4071               ns_name,
4072               vnf_name,
4073               scaling_group,
4074               scale_in,
4075               scale_out,
4076               timeout,
4077               wait):
4078     """
4079     Executes a VNF scale (adding/removing VDUs)
4080
4081     \b
4082     NS_NAME: name or ID of the NS instance.
4083     VNF_NAME: member-vnf-index in the NS to be scaled.
4084     """
4085 0     logger.debug("")
4086     # try:
4087 0     check_client_version(ctx.obj, ctx.command.name)
4088 0     if not scale_in and not scale_out:
4089 0         scale_out = True
4090 0     ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out, wait, timeout)
4091     # except ClientException as e:
4092     #     print(str(e))
4093     #     exit(1)
4094
4095
4096 ##############################
4097 # Role Management Operations #
4098 ##############################
4099
4100 0 @cli_osm.command(name='role-create', short_help='creates a new role')
4101 0 @click.argument('name')
4102 0 @click.option('--permissions',
4103               default=None,
4104               help='role permissions using a dictionary')
4105 0 @click.pass_context
4106 def role_create(ctx, name, permissions):
4107     """
4108     Creates a new role.
4109
4110     \b
4111     NAME: Name or ID of the role.
4112     DEFINITION: Definition of grant/denial of access to resources.
4113     """
4114 0     logger.debug("")
4115     # try:
4116 0     check_client_version(ctx.obj, ctx.command.name)
4117 0     ctx.obj.role.create(name, permissions)
4118     # except ClientException as e:
4119     #     print(str(e))
4120     #     exit(1)
4121
4122
4123 0 @cli_osm.command(name='role-update', short_help='updates a role')
4124 0 @click.argument('name')
4125 0 @click.option('--set-name',
4126               default=None,
4127               help='change name of rle')
4128 # @click.option('--permissions',
4129 #               default=None,
4130 #               help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete')
4131 0 @click.option('--add',
4132               default=None,
4133               help='yaml format dictionary with permission: True/False to access grant/denial')
4134 0 @click.option('--remove',
4135               default=None,
4136               help='yaml format list to remove a permission')
4137 0 @click.pass_context
4138 def role_update(ctx, name, set_name, add, remove):
4139     """
4140     Updates a role.
4141
4142     \b
4143     NAME: Name or ID of the role.
4144     DEFINITION: Definition overwrites the old definition.
4145     ADD: Grant/denial of access to resource to add.
4146     REMOVE: Grant/denial of access to resource to remove.
4147     """
4148 0     logger.debug("")
4149     # try:
4150 0     check_client_version(ctx.obj, ctx.command.name)
4151 0     ctx.obj.role.update(name, set_name, None, add, remove)
4152     # except ClientException as e:
4153     #     print(str(e))
4154     #     exit(1)
4155
4156
4157 0 @cli_osm.command(name='role-delete', short_help='deletes a role')
4158 0 @click.argument('name')
4159 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
4160 0 @click.pass_context
4161 def role_delete(ctx, name):
4162     """
4163     Deletes a role.
4164
4165     \b
4166     NAME: Name or ID of the role.
4167     """
4168 0     logger.debug("")
4169     # try:
4170 0     check_client_version(ctx.obj, ctx.command.name)
4171 0     ctx.obj.role.delete(name)
4172     # except ClientException as e:
4173     #     print(str(e))
4174     #     exit(1)
4175
4176
4177 0 @cli_osm.command(name='role-list', short_help='list all roles')
4178 0 @click.option('--filter', default=None, multiple=True,
4179               help='restricts the list to the projects matching the filter')
4180 0 @click.pass_context
4181 def role_list(ctx, filter):
4182     """
4183     List all roles.
4184     """
4185 0     logger.debug("")
4186     # try:
4187 0     check_client_version(ctx.obj, ctx.command.name)
4188 0     if filter:
4189 0         filter='&'.join(filter)
4190 0     resp = ctx.obj.role.list(filter)
4191     # except ClientException as e:
4192     #     print(str(e))
4193     #     exit(1)
4194 0     table = PrettyTable(['name', 'id'])
4195 0     for role in resp:
4196 0         table.add_row([role['name'], role['_id']])
4197 0     table.align = 'l'
4198 0     print(table)
4199
4200
4201 0 @cli_osm.command(name='role-show', short_help='show specific role')
4202 0 @click.argument('name')
4203 0 @click.pass_context
4204 def role_show(ctx, name):
4205     """
4206     Shows the details of a role.
4207
4208     \b
4209     NAME: Name or ID of the role.
4210     """
4211 0     logger.debug("")
4212     # try:
4213 0     check_client_version(ctx.obj, ctx.command.name)
4214 0     resp = ctx.obj.role.get(name)
4215     # except ClientException as e:
4216     #     print(str(e))
4217     #     exit(1)
4218
4219 0     table = PrettyTable(['key', 'attribute'])
4220 0     for k, v in resp.items():
4221 0         table.add_row([k, json.dumps(v, indent=2)])
4222 0     table.align = 'l'
4223 0     print(table)
4224
4225
4226 0 @cli_osm.command(name='package-create',
4227              short_help='Create empty NS package structure')
4228 0 @click.argument('package-type')
4229 0 @click.argument('package-name')
4230 0 @click.option('--base-directory',
4231               default='.',
4232               help=('(NS/VNF/NST) Set the location for package creation. Default: "."'))
4233 0 @click.option('--image',
4234               default="image-name",
4235               help='(VNF) Set the name of the vdu image. Default "image-name"')
4236 0 @click.option('--vdus',
4237               default=1,
4238               help='(VNF) Set the number of vdus in a VNF. Default 1')
4239 0 @click.option('--vcpu',
4240               default=1,
4241               help='(VNF) Set the number of virtual CPUs in a vdu. Default 1')
4242 0 @click.option('--memory',
4243               default=1024,
4244               help='(VNF) Set the memory size (MB) of the vdu. Default 1024')
4245 0 @click.option('--storage',
4246               default=10,
4247               help='(VNF) Set the disk size (GB) of the vdu. Default 10')
4248 0 @click.option('--interfaces',
4249               default=0,
4250               help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0')
4251 0 @click.option('--vendor',
4252               default="OSM",
4253               help='(NS/VNF) Set the descriptor vendor. Default "OSM"')
4254 0 @click.option('--override',
4255               default=False,
4256               is_flag=True,
4257               help='(NS/VNF/NST) Flag for overriding the package if exists.')
4258 0 @click.option('--detailed',
4259               is_flag=True,
4260               default=False,
4261               help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options')
4262 0 @click.option('--netslice-subnets',
4263               default=1,
4264               help='(NST) Number of netslice subnets. Default 1')
4265 0 @click.option('--netslice-vlds',
4266               default=1,
4267               help='(NST) Number of netslice vlds. Default 1')
4268 0 @click.option(
4269     "--old", default=False, is_flag=True, help="Support flag for old versions of the OSM IM (OSM<9)"
4270 )
4271 0 @click.pass_context
4272 def package_create(ctx,
4273                    package_type,
4274                    base_directory,
4275                    package_name,
4276                    override,
4277                    image,
4278                    vdus,
4279                    vcpu,
4280                    memory,
4281                    storage,
4282                    interfaces,
4283                    vendor,
4284                    detailed,
4285                    netslice_subnets,
4286                    netslice_vlds,
4287                    old,):
4288     """
4289     Creates an OSM NS, VNF, NST package
4290
4291     \b
4292     PACKAGE_TYPE: Package to be created: NS, VNF or NST.
4293     PACKAGE_NAME: Name of the package to create the folder with the content.
4294     """
4295
4296     # try:
4297 0     logger.debug("")
4298 0     check_client_version(ctx.obj, ctx.command.name)
4299 0     print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name))
4300 0     resp = ctx.obj.package_tool.create(package_type,
4301                                        base_directory,
4302                                        package_name,
4303                                        override=override,
4304                                        image=image,
4305                                        vdus=vdus,
4306                                        vcpu=vcpu,
4307                                        memory=memory,
4308                                        storage=storage,
4309                                        interfaces=interfaces,
4310                                        vendor=vendor,
4311                                        detailed=detailed,
4312                                        netslice_subnets=netslice_subnets,
4313                                        netslice_vlds=netslice_vlds,
4314                                        old=old,)
4315 0     print(resp)
4316     # except ClientException as inst:
4317     #     print("ERROR: {}".format(inst))
4318     #     exit(1)
4319
4320 0 @cli_osm.command(name='package-validate',
4321                  short_help='Validate descriptors given a base directory')
4322 0 @click.argument('base-directory',
4323                 default=".",
4324                 required=False)
4325 0 @click.option('--recursive/--no-recursive',
4326               default=True,
4327               help='The activated recursive option will validate the yaml files'
4328                    ' within the indicated directory and in its subdirectories')
4329 0 @click.option('--old',
4330               is_flag=True,
4331               default=False,
4332               help='Validates also the descriptors using the previous OSM format (pre SOL006)')
4333 0 @click.pass_context
4334 def package_validate(ctx,
4335                      base_directory,
4336                      recursive,
4337                      old):
4338     """
4339     Validate descriptors given a base directory.
4340
4341     \b
4342     BASE_DIRECTORY: Base folder for NS, VNF or NST package.
4343     """
4344     # try:
4345 0     logger.debug("")
4346 0     check_client_version(ctx.obj, ctx.command.name)
4347 0     results = ctx.obj.package_tool.validate(base_directory, recursive, old)
4348 0     table = PrettyTable()
4349 0     table.field_names = ["TYPE", "PATH", "VALID", "ERROR"]
4350     # Print the dictionary generated by the validation function
4351 0     for result in results:
4352 0         table.add_row([result["type"], result["path"], result["valid"], result["error"]])
4353 0     table.sortby = "VALID"
4354 0     table.align["PATH"] = "l"
4355 0     table.align["TYPE"] = "l"
4356 0     table.align["ERROR"] = "l"
4357 0     print(table)
4358     # except ClientException as inst:
4359     #     print("ERROR: {}".format(inst))
4360     #     exit(1)
4361
4362 0 @cli_osm.command(name='package-translate',
4363                  short_help='Translate descriptors given a base directory')
4364 0 @click.argument('base-directory',
4365                 default=".",
4366                 required=False)
4367 0 @click.option('--recursive/--no-recursive',
4368               default=True,
4369               help='The activated recursive option will translate the yaml files'
4370                    ' within the indicated directory and in its subdirectories')
4371 0 @click.option('--dryrun',
4372               is_flag=True,
4373               default=False,
4374               help='Do not translate yet, only make a dry-run to test translation')
4375 0 @click.pass_context
4376 def package_translate(ctx,
4377                      base_directory,
4378                      recursive,
4379                      dryrun):
4380     """
4381     Translate descriptors given a base directory.
4382
4383     \b
4384     BASE_DIRECTORY: Stub folder for NS, VNF or NST package.
4385     """
4386 0     logger.debug("")
4387 0     check_client_version(ctx.obj, ctx.command.name)
4388 0     results = ctx.obj.package_tool.translate(base_directory, recursive, dryrun)
4389 0     table = PrettyTable()
4390 0     table.field_names = ["CURRENT TYPE", "NEW TYPE", "PATH", "VALID", "TRANSLATED", "ERROR"]
4391     # Print the dictionary generated by the validation function
4392 0     for result in results:
4393 0         table.add_row([result["current type"], result["new type"], result["path"], result["valid"], result["translated"], result["error"]])
4394 0     table.sortby = "TRANSLATED"
4395 0     table.align["PATH"] = "l"
4396 0     table.align["TYPE"] = "l"
4397 0     table.align["ERROR"] = "l"
4398 0     print(table)
4399     # except ClientException as inst:
4400     #     print("ERROR: {}".format(inst))
4401     #     exit(1)
4402
4403 0 @cli_osm.command(name='package-build',
4404              short_help='Build the tar.gz of the package')
4405 0 @click.argument('package-folder')
4406 0 @click.option('--skip-validation',
4407               default=False,
4408               is_flag=True,
4409               help='skip package validation')
4410 0 @click.option('--skip-charm-build', default=False, is_flag=True,
4411               help='the charm will not be compiled, it is assumed to already exist')
4412 0 @click.pass_context
4413 def package_build(ctx,
4414                   package_folder,
4415                   skip_validation,
4416                   skip_charm_build):
4417     """
4418     Build the package NS, VNF given the package_folder.
4419
4420     \b
4421     PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged
4422     """
4423     # try:
4424 0     logger.debug("")
4425 0     check_client_version(ctx.obj, ctx.command.name)
4426 0     results = ctx.obj.package_tool.build(package_folder,
4427                                          skip_validation=skip_validation,
4428                                          skip_charm_build=skip_charm_build)
4429 0     print(results)
4430     # except ClientException as inst:
4431     #     print("ERROR: {}".format(inst))
4432     #     exit(1)
4433
4434 0 @cli_osm.command(name='descriptor-translate',
4435                  short_help='Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output')
4436 0 @click.argument('descriptor-file',
4437                 required=True)
4438 0 @click.pass_context
4439 def descriptor_translate(ctx,
4440                          descriptor_file):
4441     """
4442     Translate input descriptor.
4443
4444     \b
4445     DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice.
4446     """
4447 0     logger.debug("")
4448 0     check_client_version(ctx.obj, ctx.command.name)
4449 0     result = ctx.obj.package_tool.descriptor_translate(descriptor_file)
4450 0     print(result)
4451
4452
4453 0 def cli():
4454 0     try:
4455 0         cli_osm()
4456 0         exit(0)
4457 0     except pycurl.error as exc:
4458 0         print(exc)
4459 0         print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified')
4460 0     except ClientException as exc:
4461 0         print("ERROR: {}".format(exc))
4462 0     except (FileNotFoundError, PermissionError) as exc:
4463 0         print("Cannot open file: {}".format(exc))
4464 0     except yaml.YAMLError as exc:
4465 0         print("Invalid YAML format: {}".format(exc))
4466 0     exit(1)
4467     # TODO capture other controlled exceptions here
4468     # TODO remove the ClientException captures from all places, unless they do something different
4469
4470
4471 0 if __name__ == '__main__':
4472 0     cli()
4473