Refactor -o option to simplify code
[osm/osmclient.git] / osmclient / cli_commands / vnf.py
1 # Copyright ETSI Contributors and Others.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 import click
17 from osmclient.common.exceptions import ClientException
18 from osmclient.common import print_output
19 from osmclient.cli_commands import utils
20 from prettytable import PrettyTable
21 import yaml
22 import json
23 import time
24 from datetime import datetime
25 import logging
26
27 logger = logging.getLogger("osmclient")
28
29
30 def vnf_list(ctx, ns, filter, long, output):
31 logger.debug("")
32 if ns or filter:
33 if ns:
34 utils.check_client_version(ctx.obj, "--ns")
35 if filter:
36 filter = "&".join(filter)
37 utils.check_client_version(ctx.obj, "--filter")
38 resp = ctx.obj.vnf.list(ns, filter)
39 else:
40 resp = ctx.obj.vnf.list()
41 fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__
42 if fullclassname == "osmclient.sol005.client.Client":
43 field_names = [
44 "vnf id",
45 "name",
46 "ns id",
47 "vnf member index",
48 "vnfd name",
49 "vim account id",
50 "ip address",
51 ]
52 if long:
53 field_names = [
54 "vnf id",
55 "name",
56 "ns id",
57 "vnf member index",
58 "vnfd name",
59 "vim account id",
60 "ip address",
61 "date",
62 "last update",
63 ]
64 table = PrettyTable(field_names)
65 for vnfr in resp:
66 name = vnfr["name"] if "name" in vnfr else "-"
67 new_row = [
68 vnfr["_id"],
69 name,
70 vnfr["nsr-id-ref"],
71 vnfr["member-vnf-index-ref"],
72 vnfr["vnfd-ref"],
73 vnfr["vim-account-id"],
74 vnfr["ip-address"],
75 ]
76 if long:
77 date = datetime.fromtimestamp(vnfr["_admin"]["created"]).strftime(
78 "%Y-%m-%dT%H:%M:%S"
79 )
80 last_update = datetime.fromtimestamp(
81 vnfr["_admin"]["modified"]
82 ).strftime("%Y-%m-%dT%H:%M:%S")
83 new_row.extend([date, last_update])
84 table.add_row(new_row)
85 else:
86 table = PrettyTable(["vnf name", "id", "operational status", "config status"])
87 for vnfr in resp:
88 if "mgmt-interface" not in vnfr:
89 vnfr["mgmt-interface"] = {}
90 vnfr["mgmt-interface"]["ip-address"] = None
91 table.add_row(
92 [
93 vnfr["name"],
94 vnfr["id"],
95 vnfr["operational-status"],
96 vnfr["config-status"],
97 ]
98 )
99 print_output.print_output(output, table.field_names, table._rows)
100
101
102 @click.command(name="vnf-list", short_help="list all NF instances")
103 @click.option(
104 "--ns", default=None, help="NS instance id or name to restrict the NF list"
105 )
106 @click.option(
107 "--filter",
108 default=None,
109 multiple=True,
110 help="restricts the list to the NF instances matching the filter.",
111 )
112 @click.option("--long", is_flag=True, help="get more details")
113 @print_output.output_option
114 @click.pass_context
115 def vnf_list1(ctx, ns, filter, long, output):
116 """list all NF instances"""
117 logger.debug("")
118 vnf_list(ctx, ns, filter, long, output)
119
120
121 @click.command(name="nf-list", short_help="list all NF instances")
122 @click.option(
123 "--ns", default=None, help="NS instance id or name to restrict the NF list"
124 )
125 @click.option(
126 "--filter",
127 default=None,
128 multiple=True,
129 help="restricts the list to the NF instances matching the filter.",
130 )
131 @click.option("--long", is_flag=True, help="get more details")
132 @print_output.output_option
133 @click.pass_context
134 def nf_list(ctx, ns, filter, long, output):
135 """list all NF instances
136
137 \b
138 Options:
139 --ns TEXT NS instance id or name to restrict the VNF list
140 --filter filterExpr Restricts the list to the VNF instances matching the filter
141
142 \b
143 filterExpr consists of one or more strings formatted according to "simpleFilterExpr",
144 concatenated using the "&" character:
145
146 \b
147 filterExpr := <simpleFilterExpr>["&"<simpleFilterExpr>]*
148 simpleFilterExpr := <attrName>["."<attrName>]*["."<op>]"="<value>[","<value>]*
149 op := "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont"
150 attrName := string
151 value := scalar value
152
153 \b
154 where:
155 * zero or more occurrences
156 ? zero or one occurrence
157 [] grouping of expressions to be used with ? and *
158 "" quotation marks for marking string constants
159 <> name separator
160
161 \b
162 "AttrName" is the name of one attribute in the data type that defines the representation
163 of the resource. The dot (".") character in "simpleFilterExpr" allows concatenation of
164 <attrName> entries to filter by attributes deeper in the hierarchy of a structured document.
165 "Op" stands for the comparison operator. If the expression has concatenated <attrName>
166 entries, it means that the operator "op" is applied to the attribute addressed by the last
167 <attrName> entry included in the concatenation. All simple filter expressions are combined
168 by the "AND" logical operator. In a concatenation of <attrName> entries in a <simpleFilterExpr>,
169 the rightmost "attrName" entry in a "simpleFilterExpr" is called "leaf attribute". The
170 concatenation of all "attrName" entries except the leaf attribute is called the "attribute
171 prefix". If an attribute referenced in an expression is an array, an object that contains a
172 corresponding array shall be considered to match the expression if any of the elements in the
173 array matches all expressions that have the same attribute prefix.
174
175 \b
176 Filter examples:
177 --filter vim-account-id=<VIM_ACCOUNT_ID>
178 --filter vnfd-ref=<VNFD_NAME>
179 --filter vdur.ip-address=<IP_ADDRESS>
180 --filter vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
181 """
182 logger.debug("")
183 vnf_list(ctx, ns, filter, long, output)
184
185
186 @click.command(name="vnf-show", short_help="shows the info of a VNF instance")
187 @click.argument("name")
188 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
189 @click.option(
190 "--filter",
191 multiple=True,
192 help="restricts the information to the fields in the filter",
193 )
194 @click.option("--kdu", default=None, help="KDU name (whose status will be shown)")
195 @print_output.output_option
196 @click.pass_context
197 def vnf_show(ctx, name, literal, filter, kdu, output):
198 """shows the info of a VNF instance
199
200 NAME: name or ID of the VNF instance
201 """
202
203 def print_kdu_status(op_info_status):
204 """print KDU status properly formatted"""
205 try:
206 op_status = yaml.safe_load(op_info_status)
207 if (
208 "namespace" in op_status
209 and "info" in op_status
210 and "last_deployed" in op_status["info"]
211 and "status" in op_status["info"]
212 and "code" in op_status["info"]["status"]
213 and "resources" in op_status["info"]["status"]
214 and "seconds" in op_status["info"]["last_deployed"]
215 ):
216 last_deployed_time = datetime.fromtimestamp(
217 op_status["info"]["last_deployed"]["seconds"]
218 ).strftime("%a %b %d %I:%M:%S %Y")
219 print("LAST DEPLOYED: {}".format(last_deployed_time))
220 print("NAMESPACE: {}".format(op_status["namespace"]))
221 status_code = "UNKNOWN"
222 if op_status["info"]["status"]["code"] == 1:
223 status_code = "DEPLOYED"
224 print("STATUS: {}".format(status_code))
225 print()
226 print("RESOURCES:")
227 print(op_status["info"]["status"]["resources"])
228 if "notes" in op_status["info"]["status"]:
229 print("NOTES:")
230 print(op_status["info"]["status"]["notes"])
231 else:
232 print(op_info_status)
233 except Exception:
234 print(op_info_status)
235
236 logger.debug("")
237 if kdu:
238 if literal:
239 raise ClientException(
240 '"--literal" option is incompatible with "--kdu" option'
241 )
242 if filter:
243 raise ClientException(
244 '"--filter" option is incompatible with "--kdu" option'
245 )
246
247 utils.check_client_version(ctx.obj, ctx.command.name)
248 resp = ctx.obj.vnf.get(name)
249
250 if kdu:
251 ns_id = resp["nsr-id-ref"]
252 op_data = {}
253 op_data["member_vnf_index"] = resp["member-vnf-index-ref"]
254 op_data["kdu_name"] = kdu
255 op_data["primitive"] = "status"
256 op_data["primitive_params"] = {}
257 op_id = ctx.obj.ns.exec_op(ns_id, op_name="action", op_data=op_data, wait=False)
258 t = 0
259 while t < 30:
260 op_info = ctx.obj.ns.get_op(op_id)
261 if op_info["operationState"] == "COMPLETED":
262 print_kdu_status(op_info["detailed-status"])
263 return
264 time.sleep(5)
265 t += 5
266 print("Could not determine KDU status")
267 return
268
269 if literal:
270 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
271 return
272
273 table = PrettyTable(["field", "value"])
274 for k, v in list(resp.items()):
275 if not filter or k in filter:
276 table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
277 print_output.print_output(output, table.field_names, table._rows)