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