blob: 3a7dfed0a494dbce4c860c92af3c2f1d84d65407 [file] [log] [blame]
Zsolt Harasztia133a452016-12-22 01:26:57 -08001#!/usr/bin/env python
2#
3# Copyright 2016 the original author or authors.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080017import argparse
18import os
Zsolt Harasztia133a452016-12-22 01:26:57 -080019import readline
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040020import sys
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080021from optparse import make_option
Zsolt Haraszti80175202016-12-24 00:17:51 -080022from time import sleep, time
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080023
Zsolt Harasztia133a452016-12-22 01:26:57 -080024import grpc
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080025import requests
26from cmd2 import Cmd, options
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040027from consul import Consul
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080028from google.protobuf.empty_pb2 import Empty
Zsolt Harasztia133a452016-12-22 01:26:57 -080029from simplejson import dumps
30
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080031from cli.device import DeviceCli
Nikolay Titov89004ec2017-06-19 18:22:42 -040032from cli.xpon import XponCli
Chip Boling69abce82018-06-18 09:56:23 -050033from cli.omci import OmciCli
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040034from cli.alarm_filters import AlarmFiltersCli
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080035from cli.logical_device import LogicalDeviceCli
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040036from cli.table import print_pb_list_as_table
Zsolt Harasztia133a452016-12-22 01:26:57 -080037from voltha.protos import third_party
Scott Bakerd865fa22018-11-07 11:45:28 -080038from voltha.protos import voltha_pb2, voltha_pb2_grpc, health_pb2_grpc
Zsolt Haraszti85f12852016-12-24 08:30:58 -080039from voltha.protos.openflow_13_pb2 import FlowTableUpdate, FlowGroupTableUpdate
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080040
Zsolt Harasztia133a452016-12-22 01:26:57 -080041_ = third_party
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040042from cli.utils import pb2dict
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080043
44defs = dict(
45 # config=os.environ.get('CONFIG', './cli.yml'),
46 consul=os.environ.get('CONSUL', 'localhost:8500'),
47 voltha_grpc_endpoint=os.environ.get('VOLTHA_GRPC_ENDPOINT',
48 'localhost:50055'),
49 voltha_sim_rest_endpoint=os.environ.get('VOLTHA_SIM_REST_ENDPOINT',
50 'localhost:18880'),
khenaidoo108f05c2017-07-06 11:15:29 -040051 global_request=os.environ.get('GLOBAL_REQUEST', False)
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080052)
53
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080054banner = """\
Zsolt Haraszti313c4be2016-12-27 11:06:53 -080055 _ _ _ ___ _ ___
56__ _____| | |_| |_ __ _ / __| | |_ _|
57\ V / _ \ | _| ' \/ _` | | (__| |__ | |
58 \_/\___/_|\__|_||_\__,_| \___|____|___|
Zsolt Haraszti80175202016-12-24 00:17:51 -080059(to exit type quit or hit Ctrl-D)
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080060"""
Zsolt Harasztia133a452016-12-22 01:26:57 -080061
Zsolt Harasztia133a452016-12-22 01:26:57 -080062
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040063class VolthaCli(Cmd):
Zsolt Harasztia133a452016-12-22 01:26:57 -080064 prompt = 'voltha'
65 history_file_name = '.voltha_cli_history'
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080066
67 # Settable CLI parameters
68 voltha_grpc = 'localhost:50055'
69 voltha_sim_rest = 'localhost:18880'
khenaidoo108f05c2017-07-06 11:15:29 -040070 global_request = False
Zsolt Harasztia133a452016-12-22 01:26:57 -080071 max_history_lines = 500
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080072 default_device_id = None
73 default_logical_device_id = None
Zsolt Harasztia133a452016-12-22 01:26:57 -080074
75 Cmd.settable.update(dict(
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080076 voltha_grpc='Voltha GRPC endpoint in form of <host>:<port>',
77 voltha_sim_rest='Voltha simulation back door for testing in form '
78 'of <host>:<port>',
79 max_history_lines='Maximum number of history lines stored across '
80 'sessions',
81 default_device_id='Device id used when no device id is specified',
82 default_logical_device_id='Logical device id used when no device id '
83 'is specified',
Zsolt Harasztia133a452016-12-22 01:26:57 -080084 ))
85
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080086 # cleanup of superfluous commands from cmd2
Zsolt Haraszti80175202016-12-24 00:17:51 -080087 del Cmd.do_cmdenvironment
Steve Crooks05f24522017-02-27 13:32:27 -050088 del Cmd.do_load
Zsolt Haraszti80175202016-12-24 00:17:51 -080089 del Cmd.do__relative_load
Zsolt Haraszti80175202016-12-24 00:17:51 -080090
khenaidoo108f05c2017-07-06 11:15:29 -040091 def __init__(self, voltha_grpc, voltha_sim_rest, global_request=False):
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080092 VolthaCli.voltha_grpc = voltha_grpc
93 VolthaCli.voltha_sim_rest = voltha_sim_rest
khenaidoo108f05c2017-07-06 11:15:29 -040094 VolthaCli.global_request = global_request
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080095 Cmd.__init__(self)
Zsolt Harasztia133a452016-12-22 01:26:57 -080096 self.prompt = '(' + self.colorize(
Zsolt Haraszti80175202016-12-24 00:17:51 -080097 self.colorize(self.prompt, 'blue'), 'bold') + ') '
Zsolt Harasztia133a452016-12-22 01:26:57 -080098 self.channel = None
khenaidoo108f05c2017-07-06 11:15:29 -040099 self.stub = None
Zsolt Haraszti80175202016-12-24 00:17:51 -0800100 self.device_ids_cache = None
101 self.device_ids_cache_ts = time()
102 self.logical_device_ids_cache = None
103 self.logical_device_ids_cache_ts = time()
Zsolt Harasztia133a452016-12-22 01:26:57 -0800104
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -0800105 # we override cmd2's method to avoid its optparse conflicting with our
106 # command line parsing
107 def cmdloop(self):
108 self._cmdloop()
109
Zsolt Harasztia133a452016-12-22 01:26:57 -0800110 def load_history(self):
111 """Load saved command history from local history file"""
112 try:
113 with file(self.history_file_name, 'r') as f:
114 for line in f.readlines():
115 stripped_line = line.strip()
116 self.history.append(stripped_line)
117 readline.add_history(stripped_line)
118 except IOError:
119 pass # ignore if file cannot be read
120
121 def save_history(self):
122 try:
Zsolt Haraszti80175202016-12-24 00:17:51 -0800123 with open(self.history_file_name, 'w') as f:
Zsolt Harasztia133a452016-12-22 01:26:57 -0800124 f.write('\n'.join(self.history[-self.max_history_lines:]))
Zsolt Haraszti80175202016-12-24 00:17:51 -0800125 except IOError as e:
126 self.perror('Could not save history in {}: {}'.format(
127 self.history_file_name, e))
Zsolt Harasztia133a452016-12-22 01:26:57 -0800128 else:
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -0800129 self.poutput('History saved as {}'.format(
Zsolt Haraszti80175202016-12-24 00:17:51 -0800130 self.history_file_name))
131
132 def perror(self, errmsg, statement=None):
133 # Touch it up to make sure error is prefixed and colored
134 Cmd.perror(self, self.colorize('***ERROR: ', 'red') + errmsg,
135 statement)
Zsolt Harasztia133a452016-12-22 01:26:57 -0800136
137 def get_channel(self):
138 if self.channel is None:
139 self.channel = grpc.insecure_channel(self.voltha_grpc)
140 return self.channel
141
khenaidoo108f05c2017-07-06 11:15:29 -0400142 def get_stub(self):
143 if self.stub is None:
144 self.stub = \
Scott Bakerd865fa22018-11-07 11:45:28 -0800145 voltha_pb2_grpc.VolthaGlobalServiceStub(self.get_channel()) \
khenaidoo108f05c2017-07-06 11:15:29 -0400146 if self.global_request else \
Scott Bakerd865fa22018-11-07 11:45:28 -0800147 voltha_pb2_grpc.VolthaLocalServiceStub(self.get_channel())
khenaidoo108f05c2017-07-06 11:15:29 -0400148 return self.stub
149
Zsolt Haraszti80175202016-12-24 00:17:51 -0800150 # ~~~~~~~~~~~~~~~~~ ACTUAL COMMAND IMPLEMENTATIONS ~~~~~~~~~~~~~~~~~~~~~~~~
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800151
Zsolt Haraszti80175202016-12-24 00:17:51 -0800152 def do_reset_history(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800153 """Reset CLI history"""
154 while self.history:
155 self.history.pop()
156
Zsolt Haraszti80175202016-12-24 00:17:51 -0800157 def do_launch(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800158 """If Voltha is not running yet, launch it"""
Zsolt Haraszti80175202016-12-24 00:17:51 -0800159 raise NotImplementedError('not implemented yet')
Zsolt Harasztia133a452016-12-22 01:26:57 -0800160
Zsolt Haraszti80175202016-12-24 00:17:51 -0800161 def do_restart(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800162 """Launch Voltha, but if it is already running, terminate it first"""
163 pass
164
Zsolt Haraszti80175202016-12-24 00:17:51 -0800165 def do_adapters(self, line):
166 """List loaded adapter"""
khenaidoo108f05c2017-07-06 11:15:29 -0400167 stub = self.get_stub()
Zsolt Haraszti80175202016-12-24 00:17:51 -0800168 res = stub.ListAdapters(Empty())
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400169 omit_fields = {'config.log_level', 'logical_device_ids'}
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800170 print_pb_list_as_table('Adapters:', res.items, omit_fields, self.poutput)
Zsolt Haraszti80175202016-12-24 00:17:51 -0800171
172 def get_devices(self):
khenaidoo108f05c2017-07-06 11:15:29 -0400173 stub = self.get_stub()
Zsolt Harasztia133a452016-12-22 01:26:57 -0800174 res = stub.ListDevices(Empty())
Zsolt Haraszti80175202016-12-24 00:17:51 -0800175 return res.items
Zsolt Harasztia133a452016-12-22 01:26:57 -0800176
Zsolt Haraszti80175202016-12-24 00:17:51 -0800177 def get_logical_devices(self):
khenaidoo108f05c2017-07-06 11:15:29 -0400178 stub = self.get_stub()
Zsolt Haraszti80175202016-12-24 00:17:51 -0800179 res = stub.ListLogicalDevices(Empty())
180 return res.items
181
182 def do_devices(self, line):
183 """List devices registered in Voltha"""
184 devices = self.get_devices()
185 omit_fields = {
186 'adapter',
187 'vendor',
188 'model',
189 'hardware_version',
ggowdru236bd952017-06-20 20:32:55 -0700190 'images',
Zsolt Haraszti80175202016-12-24 00:17:51 -0800191 'firmware_version',
Nicolas Palpacuerb83853e2018-06-28 16:11:30 -0400192 'vendor_id'
Zsolt Haraszti80175202016-12-24 00:17:51 -0800193 }
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800194 print_pb_list_as_table('Devices:', devices, omit_fields, self.poutput)
Zsolt Haraszti80175202016-12-24 00:17:51 -0800195
196 def do_logical_devices(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800197 """List logical devices in Voltha"""
khenaidoo108f05c2017-07-06 11:15:29 -0400198 stub = self.get_stub()
Zsolt Harasztia133a452016-12-22 01:26:57 -0800199 res = stub.ListLogicalDevices(Empty())
Zsolt Haraszti80175202016-12-24 00:17:51 -0800200 omit_fields = {
201 'desc.mfr_desc',
202 'desc.hw_desc',
203 'desc.sw_desc',
204 'desc.dp_desc',
205 'desc.serial_number',
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400206 'switch_features.capabilities'
Zsolt Haraszti80175202016-12-24 00:17:51 -0800207 }
Jonathan Hart7d4a23d2018-06-28 07:36:28 -0700208 presfns = {
209 'datapath_id': lambda x: "{0:0{1}x}".format(int(x), 16)
210 }
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800211 print_pb_list_as_table('Logical devices:', res.items, omit_fields,
Jonathan Hart7d4a23d2018-06-28 07:36:28 -0700212 self.poutput, presfns=presfns)
Zsolt Harasztia133a452016-12-22 01:26:57 -0800213
Zsolt Haraszti80175202016-12-24 00:17:51 -0800214 def do_device(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800215 """Enter device level command mode"""
Zsolt Haraszti80175202016-12-24 00:17:51 -0800216 device_id = line.strip() or self.default_device_id
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800217 if not device_id:
218 raise Exception('<device-id> parameter needed')
Venkata Telu133b27d2018-06-12 14:22:28 -0500219 if device_id not in self.device_ids():
Venkata Telu35cc4722018-06-01 12:05:30 -0500220 self.poutput( self.colorize('Error: ', 'red') +
221 'There is no such device')
222 raise Exception('<device-id> is not a valid one')
khenaidoo108f05c2017-07-06 11:15:29 -0400223 sub = DeviceCli(device_id, self.get_stub)
Zsolt Harasztia133a452016-12-22 01:26:57 -0800224 sub.cmdloop()
225
Zsolt Haraszti80175202016-12-24 00:17:51 -0800226 def do_logical_device(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800227 """Enter logical device level command mode"""
Zsolt Haraszti80175202016-12-24 00:17:51 -0800228 logical_device_id = line.strip() or self.default_logical_device_id
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800229 if not logical_device_id:
230 raise Exception('<logical-device-id> parameter needed')
Venkata Telu133b27d2018-06-12 14:22:28 -0500231 if logical_device_id not in self.logical_device_ids():
Venkata Telu35cc4722018-06-01 12:05:30 -0500232 self.poutput( self.colorize('Error: ', 'red') +
233 'There is no such device')
234 raise Exception('<logical-device-id> is not a valid one')
khenaidoo108f05c2017-07-06 11:15:29 -0400235 sub = LogicalDeviceCli(logical_device_id, self.get_stub)
Zsolt Harasztia133a452016-12-22 01:26:57 -0800236 sub.cmdloop()
237
Zsolt Haraszti80175202016-12-24 00:17:51 -0800238 def device_ids(self, force_refresh=False):
239 if force_refresh or self.device_ids is None or \
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400240 (time() - self.device_ids_cache_ts) > 1:
Zsolt Haraszti80175202016-12-24 00:17:51 -0800241 self.device_ids_cache = [d.id for d in self.get_devices()]
242 self.device_ids_cache_ts = time()
243 return self.device_ids_cache
244
245 def logical_device_ids(self, force_refresh=False):
246 if force_refresh or self.logical_device_ids is None or \
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400247 (time() - self.logical_device_ids_cache_ts) > 1:
Zsolt Haraszti80175202016-12-24 00:17:51 -0800248 self.logical_device_ids_cache = [d.id for d
249 in self.get_logical_devices()]
250 self.logical_device_ids_cache_ts = time()
251 return self.logical_device_ids_cache
252
253 def complete_device(self, text, line, begidx, endidx):
254 if not text:
255 completions = self.device_ids()[:]
256 else:
257 completions = [d for d in self.device_ids() if d.startswith(text)]
258 return completions
259
260 def complete_logical_device(self, text, line, begidx, endidx):
261 if not text:
262 completions = self.logical_device_ids()[:]
263 else:
264 completions = [d for d in self.logical_device_ids()
265 if d.startswith(text)]
266 return completions
267
Nikolay Titov89004ec2017-06-19 18:22:42 -0400268 def do_xpon(self, line):
269 """xpon <optional> [device_ID] - Enter xpon level command mode"""
270 device_id = line.strip()
Nikolay Titov3f0c9dd2017-07-17 17:37:25 -0400271 if device_id:
272 stub = self.get_stub()
273 try:
274 res = stub.GetDevice(voltha_pb2.ID(id=device_id))
275 except Exception:
Nikolay Titov176f1db2017-08-10 12:38:43 -0400276 self.poutput(
277 self.colorize('Error: ', 'red') + 'No device id ' +
278 self.colorize(device_id, 'blue') + ' is found')
Nikolay Titov3f0c9dd2017-07-17 17:37:25 -0400279 return
280 sub = XponCli(self.get_channel, device_id)
Nikolay Titov89004ec2017-06-19 18:22:42 -0400281 sub.cmdloop()
282
Chip Boling69abce82018-06-18 09:56:23 -0500283 def do_omci(self, line):
284 """omci <device_ID> - Enter OMCI level command mode"""
285
286 device_id = line.strip() or self.default_device_id
287 if not device_id:
288 raise Exception('<device-id> parameter needed')
289 sub = OmciCli(device_id, self.get_stub)
290 sub.cmdloop()
291
Zsolt Haraszti80175202016-12-24 00:17:51 -0800292 def do_pdb(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800293 """Launch PDB debug prompt in CLI (for CLI development)"""
294 from pdb import set_trace
295 set_trace()
296
Jonathan Hartda93ac62018-05-01 11:25:29 -0700297 def do_version(self, line):
298 """Show the VOLTHA core version"""
299 stub = self.get_stub()
300 voltha = stub.GetVoltha(Empty())
301 self.poutput('{}'.format(voltha.version))
302
Zsolt Haraszti80175202016-12-24 00:17:51 -0800303 def do_health(self, line):
Zsolt Harasztia133a452016-12-22 01:26:57 -0800304 """Show connectivity status to Voltha status"""
Scott Bakerd865fa22018-11-07 11:45:28 -0800305 stub = health_pb2_grpc.HealthServiceStub(self.get_channel())
Zsolt Harasztia133a452016-12-22 01:26:57 -0800306 res = stub.GetHealthStatus(Empty())
Zsolt Haraszti80175202016-12-24 00:17:51 -0800307 self.poutput(dumps(pb2dict(res), indent=4))
Zsolt Harasztia133a452016-12-22 01:26:57 -0800308
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800309 @options([
310 make_option('-t', '--device-type', action="store", dest='device_type',
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400311 help="Device type", default='simulated_olt'),
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800312 make_option('-m', '--mac-address', action='store', dest='mac_address',
313 default='00:0c:e2:31:40:00'),
314 make_option('-i', '--ip-address', action='store', dest='ip_address'),
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800315 make_option('-H', '--host_and_port', action='store',
316 dest='host_and_port'),
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800317 ])
Zsolt Haraszti80175202016-12-24 00:17:51 -0800318 def do_preprovision_olt(self, line, opts):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800319 """Preprovision a new OLT with given device type"""
khenaidoo108f05c2017-07-06 11:15:29 -0400320 stub = self.get_stub()
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800321 kw = dict(type=opts.device_type)
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800322 if opts.host_and_port:
323 kw['host_and_port'] = opts.host_and_port
324 elif opts.ip_address:
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800325 kw['ipv4_address'] = opts.ip_address
326 elif opts.mac_address:
Venkata Teludc1a15b2018-07-06 14:31:05 -0500327 kw['mac_address'] = opts.mac_address.lower()
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800328 else:
329 raise Exception('Either IP address or Mac Address is needed')
Chip Boling90b224d2017-06-02 11:51:48 -0500330 # Pass any extra arguments past '--' to the device as custom arguments
331 kw['extra_args'] = line
332
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800333 device = voltha_pb2.Device(**kw)
334 device = stub.CreateDevice(device)
Zsolt Haraszti80175202016-12-24 00:17:51 -0800335 self.poutput('success (device id = {})'.format(device.id))
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800336 self.default_device_id = device.id
Zsolt Harasztia133a452016-12-22 01:26:57 -0800337
Khen Nursimulud068d812017-03-06 11:44:18 -0500338 def do_enable(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800339 """
Khen Nursimulud068d812017-03-06 11:44:18 -0500340 Enable a device. If the <id> is not provided, it will be on the last
341 pre-provisioned device.
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800342 """
Zsolt Haraszti80175202016-12-24 00:17:51 -0800343 device_id = line or self.default_device_id
Venkata Telu0ccc4302018-07-27 15:11:13 -0500344 if device_id not in self.device_ids():
345 self.poutput('Error: There is no such preprovisioned device')
346 return
347
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400348 try:
khenaidoo108f05c2017-07-06 11:15:29 -0400349 stub = self.get_stub()
Venkata Telu0ccc4302018-07-27 15:11:13 -0500350 device = stub.GetDevice(voltha_pb2.ID(id=device_id))
351 if device.admin_state == voltha_pb2.AdminState.ENABLED:
Nicolas Palpacuer5807dfc2018-08-27 15:47:03 -0400352 if device.oper_status != voltha_pb2.OperStatus.ACTIVATING:
353 self.poutput('Error: Device is already enabled')
354 return
355 else:
356 stub.EnableDevice(voltha_pb2.ID(id=device_id))
357 self.poutput('enabling {}'.format(device_id))
Zsolt Harasztia133a452016-12-22 01:26:57 -0800358
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400359 while True:
360 device = stub.GetDevice(voltha_pb2.ID(id=device_id))
361 # If this is an OLT then acquire logical device id
362 if device.oper_status == voltha_pb2.OperStatus.ACTIVE:
363 if device.type.endswith('_olt'):
364 assert device.parent_id
365 self.default_logical_device_id = device.parent_id
366 self.poutput('success (logical device id = {})'.format(
367 self.default_logical_device_id))
368 else:
369 self.poutput('success (device id = {})'.format(device.id))
370 break
371 self.poutput('waiting for device to be enabled...')
372 sleep(.5)
Chip Boling69abce82018-06-18 09:56:23 -0500373 except Exception as e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400374 self.poutput('Error enabling {}. Error:{}'.format(device_id, e))
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800375
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800376 complete_activate_olt = complete_device
377
Khen Nursimulud068d812017-03-06 11:44:18 -0500378 def do_reboot(self, line):
379 """
380 Rebooting a device. ID of the device needs to be provided
381 """
382 device_id = line or self.default_device_id
383 self.poutput('rebooting {}'.format(device_id))
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400384 try:
khenaidoo108f05c2017-07-06 11:15:29 -0400385 stub = self.get_stub()
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400386 stub.RebootDevice(voltha_pb2.ID(id=device_id))
387 self.poutput('rebooted {}'.format(device_id))
ggowdru64d738a2018-05-10 07:08:06 -0700388 except Exception as e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400389 self.poutput('Error rebooting {}. Error:{}'.format(device_id, e))
Khen Nursimulud068d812017-03-06 11:44:18 -0500390
sathishg5ae86222017-06-28 15:16:29 +0530391 def do_self_test(self, line):
392 """
393 Self Test a device. ID of the device needs to be provided
394 """
395 device_id = line or self.default_device_id
396 self.poutput('Self Testing {}'.format(device_id))
397 try:
khenaidoo108f05c2017-07-06 11:15:29 -0400398 stub = self.get_stub()
sathishg5ae86222017-06-28 15:16:29 +0530399 res = stub.SelfTest(voltha_pb2.ID(id=device_id))
400 self.poutput('Self Tested {}'.format(device_id))
401 self.poutput(dumps(pb2dict(res), indent=4))
ggowdru64d738a2018-05-10 07:08:06 -0700402 except Exception as e:
sathishg5ae86222017-06-28 15:16:29 +0530403 self.poutput('Error in self test {}. Error:{}'.format(device_id, e))
404
Khen Nursimulud068d812017-03-06 11:44:18 -0500405 def do_delete(self, line):
406 """
407 Deleting a device. ID of the device needs to be provided
408 """
409 device_id = line or self.default_device_id
410 self.poutput('deleting {}'.format(device_id))
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400411 try:
khenaidoo108f05c2017-07-06 11:15:29 -0400412 stub = self.get_stub()
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400413 stub.DeleteDevice(voltha_pb2.ID(id=device_id))
414 self.poutput('deleted {}'.format(device_id))
ggowdru64d738a2018-05-10 07:08:06 -0700415 except Exception as e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400416 self.poutput('Error deleting {}. Error:{}'.format(device_id, e))
Khen Nursimulud068d812017-03-06 11:44:18 -0500417
418 def do_disable(self, line):
419 """
420 Disable a device. ID of the device needs to be provided
421 """
422 device_id = line
Venkata Teluf468de82018-08-07 13:03:58 -0500423 if device_id not in self.device_ids():
424 self.poutput('Error: There is no such device')
425 return
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400426 try:
khenaidoo108f05c2017-07-06 11:15:29 -0400427 stub = self.get_stub()
Venkata Teluf468de82018-08-07 13:03:58 -0500428 device = stub.GetDevice(voltha_pb2.ID(id=device_id))
429 if device.admin_state == voltha_pb2.AdminState.DISABLED:
430 self.poutput('Error: Device is already disabled')
431 return
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400432 stub.DisableDevice(voltha_pb2.ID(id=device_id))
Venkata Teluf468de82018-08-07 13:03:58 -0500433 self.poutput('disabling {}'.format(device_id))
Khen Nursimulud068d812017-03-06 11:44:18 -0500434
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400435 # Do device query and verify that the device admin status is
436 # DISABLED and Operational Status is unknown
437 device = stub.GetDevice(voltha_pb2.ID(id=device_id))
ggowdru64d738a2018-05-10 07:08:06 -0700438 if device.admin_state == voltha_pb2.AdminState.DISABLED:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400439 self.poutput('disabled successfully {}'.format(device_id))
440 else:
441 self.poutput('disabling failed {}. Admin State:{} '
442 'Operation State: {}'.format(device_id,
443 device.admin_state,
444 device.oper_status))
ggowdru64d738a2018-05-10 07:08:06 -0700445 except Exception as e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400446 self.poutput('Error disabling {}. Error:{}'.format(device_id, e))
Khen Nursimulud068d812017-03-06 11:44:18 -0500447
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800448 def do_test(self, line):
449 """Enter test mode, which makes a bunch on new commands available"""
khenaidoo108f05c2017-07-06 11:15:29 -0400450 sub = TestCli(self.history, self.voltha_grpc,
451 self.get_stub, self.voltha_sim_rest)
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800452 sub.cmdloop()
453
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400454 def do_alarm_filters(self, line):
khenaidoo108f05c2017-07-06 11:15:29 -0400455 sub = AlarmFiltersCli(self.get_stub)
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400456 sub.cmdloop()
457
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800458
459class TestCli(VolthaCli):
khenaidoo108f05c2017-07-06 11:15:29 -0400460 def __init__(self, history, voltha_grpc, get_stub, voltha_sim_rest):
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800461 VolthaCli.__init__(self, voltha_grpc, voltha_sim_rest)
462 self.history = history
khenaidoo108f05c2017-07-06 11:15:29 -0400463 self.get_stub = get_stub
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800464 self.prompt = '(' + self.colorize(self.colorize('test', 'cyan'),
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400465 'bold') + ') '
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800466
467 def get_device(self, device_id, depth=0):
khenaidoo108f05c2017-07-06 11:15:29 -0400468 stub = self.get_stub()
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800469 res = stub.GetDevice(voltha_pb2.ID(id=device_id),
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400470 metadata=(('get-depth', str(depth)),))
Zsolt Haraszti50cae7d2017-01-08 22:27:07 -0800471 return res
Zsolt Haraszti80175202016-12-24 00:17:51 -0800472
473 def do_arrive_onus(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800474 """
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800475 Simulate the arrival of ONUs (available only on simulated_olt)
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800476 """
Zsolt Haraszti80175202016-12-24 00:17:51 -0800477 device_id = line or self.default_device_id
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800478
479 # verify that device is of type simulated_olt
480 device = self.get_device(device_id)
481 assert device.type == 'simulated_olt', (
482 'Cannot use it on this device type (only on simulated_olt type)')
483
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800484 requests.get('http://{}/devices/{}/detect_onus'.format(
485 self.voltha_sim_rest, device_id
486 ))
487
Zsolt Haraszti80175202016-12-24 00:17:51 -0800488 complete_arrive_onus = VolthaCli.complete_device
489
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800490 def get_logical_ports(self, logical_device_id):
491 """
492 Return the NNI port number and the first usable UNI port of logical
493 device, and the vlan associated with the latter.
494 """
khenaidoo108f05c2017-07-06 11:15:29 -0400495 stub = self.get_stub()
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800496 ports = stub.ListLogicalDevicePorts(
497 voltha_pb2.ID(id=logical_device_id)).items
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800498 nni = None
499 unis = []
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800500 for port in ports:
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800501 if port.root_port:
502 assert nni is None, "There shall be only one root port"
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800503 nni = port.ofp_port.port_no
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800504 else:
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800505 uni = port.ofp_port.port_no
506 uni_device = self.get_device(port.device_id)
507 vlan = uni_device.vlan
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800508 unis.append((uni, vlan))
509
510 assert nni is not None, "No NNI port found"
511 assert unis, "Not a single UNI?"
512
513 return nni, unis
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800514
Zsolt Haraszti80175202016-12-24 00:17:51 -0800515 def do_install_eapol_flow(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800516 """
517 Install an EAPOL flow on the given logical device. If device is not
518 given, it will be applied to logical device of the last pre-provisioned
519 OLT device.
520 """
Zsolt Haraszti80175202016-12-24 00:17:51 -0800521 logical_device_id = line or self.default_logical_device_id
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800522
523 # gather NNI and UNI port IDs
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800524 nni_port_no, unis = self.get_logical_ports(logical_device_id)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800525
526 # construct and push flow rule
khenaidoo108f05c2017-07-06 11:15:29 -0400527 stub = self.get_stub()
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800528 for uni_port_no, _ in unis:
529 update = FlowTableUpdate(
530 id=logical_device_id,
531 flow_mod=mk_simple_flow_mod(
532 priority=2000,
533 match_fields=[in_port(uni_port_no), eth_type(0x888e)],
534 actions=[
535 # push_vlan(0x8100),
536 # set_field(vlan_vid(4096 + 4000)),
537 output(ofp.OFPP_CONTROLLER)
538 ]
539 )
540 )
541 res = stub.UpdateLogicalDeviceFlowTable(update)
542 self.poutput('success for uni {} ({})'.format(uni_port_no, res))
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800543
Zsolt Haraszti80175202016-12-24 00:17:51 -0800544 complete_install_eapol_flow = VolthaCli.complete_logical_device
545
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800546 def do_install_all_controller_bound_flows(self, line):
547 """
548 Install all flow rules for controller bound flows, including EAPOL,
549 IGMP and DHCP. If device is not given, it will be applied to logical
550 device of the last pre-provisioned OLT device.
551 """
552 logical_device_id = line or self.default_logical_device_id
553
554 # gather NNI and UNI port IDs
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800555 nni_port_no, unis = self.get_logical_ports(logical_device_id)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800556
557 # construct and push flow rules
khenaidoo108f05c2017-07-06 11:15:29 -0400558 stub = self.get_stub()
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800559
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800560 for uni_port_no, _ in unis:
561 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
562 id=logical_device_id,
563 flow_mod=mk_simple_flow_mod(
564 priority=2000,
565 match_fields=[
566 in_port(uni_port_no),
567 eth_type(0x888e)
568 ],
569 actions=[output(ofp.OFPP_CONTROLLER)]
570 )
571 ))
572 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
573 id=logical_device_id,
574 flow_mod=mk_simple_flow_mod(
575 priority=1000,
576 match_fields=[
577 in_port(uni_port_no),
578 eth_type(0x800),
579 ip_proto(2)
580 ],
581 actions=[output(ofp.OFPP_CONTROLLER)]
582 )
583 ))
584 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
585 id=logical_device_id,
586 flow_mod=mk_simple_flow_mod(
587 priority=1000,
588 match_fields=[
589 in_port(uni_port_no),
590 eth_type(0x800),
591 ip_proto(17),
592 udp_dst(67)
593 ],
594 actions=[output(ofp.OFPP_CONTROLLER)]
595 )
596 ))
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800597 self.poutput('success')
598
599 complete_install_all_controller_bound_flows = \
600 VolthaCli.complete_logical_device
601
602 def do_install_all_sample_flows(self, line):
603 """
604 Install all flows that are representative of the virtualized access
605 scenario in a PON network.
606 """
607 logical_device_id = line or self.default_logical_device_id
608
609 # gather NNI and UNI port IDs
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800610 nni_port_no, unis = self.get_logical_ports(logical_device_id)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800611
612 # construct and push flow rules
khenaidoo108f05c2017-07-06 11:15:29 -0400613 stub = self.get_stub()
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800614
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800615 for uni_port_no, c_vid in unis:
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800616 # Controller-bound flows
617 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
618 id=logical_device_id,
619 flow_mod=mk_simple_flow_mod(
620 priority=2000,
621 match_fields=[in_port(uni_port_no), eth_type(0x888e)],
622 actions=[
623 # push_vlan(0x8100),
624 # set_field(vlan_vid(4096 + 4000)),
625 output(ofp.OFPP_CONTROLLER)
626 ]
627 )
628 ))
629 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
630 id=logical_device_id,
631 flow_mod=mk_simple_flow_mod(
632 priority=1000,
633 match_fields=[eth_type(0x800), ip_proto(2)],
634 actions=[output(ofp.OFPP_CONTROLLER)]
635 )
636 ))
637 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
638 id=logical_device_id,
639 flow_mod=mk_simple_flow_mod(
640 priority=1000,
641 match_fields=[eth_type(0x800), ip_proto(17), udp_dst(67)],
642 actions=[output(ofp.OFPP_CONTROLLER)]
643 )
644 ))
645
646 # Unicast flows:
647 # Downstream flow 1
648 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
649 id=logical_device_id,
650 flow_mod=mk_simple_flow_mod(
651 priority=500,
652 match_fields=[
653 in_port(nni_port_no),
654 vlan_vid(4096 + 1000),
655 metadata(c_vid) # here to mimic an ONOS artifact
656 ],
657 actions=[pop_vlan()],
658 next_table_id=1
659 )
660 ))
661 # Downstream flow 2
662 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
663 id=logical_device_id,
664 flow_mod=mk_simple_flow_mod(
665 priority=500,
666 table_id=1,
667 match_fields=[in_port(nni_port_no), vlan_vid(4096 + c_vid)],
668 actions=[set_field(vlan_vid(4096 + 0)), output(uni_port_no)]
669 )
670 ))
671 # Upstream flow 1 for 0-tagged case
672 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
673 id=logical_device_id,
674 flow_mod=mk_simple_flow_mod(
675 priority=500,
676 match_fields=[in_port(uni_port_no), vlan_vid(4096 + 0)],
677 actions=[set_field(vlan_vid(4096 + c_vid))],
678 next_table_id=1
679 )
680 ))
681 # Upstream flow 1 for untagged case
682 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
683 id=logical_device_id,
684 flow_mod=mk_simple_flow_mod(
685 priority=500,
686 match_fields=[in_port(uni_port_no), vlan_vid(0)],
687 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + c_vid))],
688 next_table_id=1
689 )
690 ))
691 # Upstream flow 2 for s-tag
692 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
693 id=logical_device_id,
694 flow_mod=mk_simple_flow_mod(
695 priority=500,
696 table_id=1,
697 match_fields=[in_port(uni_port_no), vlan_vid(4096 + c_vid)],
698 actions=[
699 push_vlan(0x8100),
700 set_field(vlan_vid(4096 + 1000)),
701 output(nni_port_no)
702 ]
703 )
704 ))
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800705
706 # Push a few multicast flows
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800707 # 1st with one bucket for our uni 0
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800708 stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
709 id=logical_device_id,
710 group_mod=mk_multicast_group_mod(
711 group_id=1,
712 buckets=[
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800713 ofp.ofp_bucket(actions=[
714 pop_vlan(),
715 output(unis[0][0])
716 ])
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800717 ]
718 )
719 ))
720 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
721 id=logical_device_id,
722 flow_mod=mk_simple_flow_mod(
723 priority=1000,
724 match_fields=[
725 in_port(nni_port_no),
726 eth_type(0x800),
727 vlan_vid(4096 + 140),
728 ipv4_dst(0xe4010101)
729 ],
730 actions=[group(1)]
731 )
732 ))
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800733
734 # 2nd with one bucket for uni 0 and 1
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800735 stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
736 id=logical_device_id,
737 group_mod=mk_multicast_group_mod(
738 group_id=2,
739 buckets=[
Nathan Knuth6b7b6ff2017-02-12 03:30:48 -0800740 ofp.ofp_bucket(actions=[pop_vlan(), output(unis[0][0])])
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400741 # ofp.ofp_bucket(actions=[pop_vlan(), output(unis[1][0])])
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800742 ]
743 )
744 ))
745 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
746 id=logical_device_id,
747 flow_mod=mk_simple_flow_mod(
748 priority=1000,
749 match_fields=[
750 in_port(nni_port_no),
751 eth_type(0x800),
752 vlan_vid(4096 + 140),
753 ipv4_dst(0xe4020202)
754 ],
755 actions=[group(2)]
756 )
757 ))
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800758
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800759 # 3rd with empty bucket
760 stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
761 id=logical_device_id,
762 group_mod=mk_multicast_group_mod(
763 group_id=3,
764 buckets=[]
765 )
766 ))
767 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
768 id=logical_device_id,
769 flow_mod=mk_simple_flow_mod(
770 priority=1000,
771 match_fields=[
772 in_port(nni_port_no),
773 eth_type(0x800),
774 vlan_vid(4096 + 140),
775 ipv4_dst(0xe4030303)
776 ],
777 actions=[group(3)]
778 )
779 ))
780
781 self.poutput('success')
782
783 complete_install_all_sample_flows = VolthaCli.complete_logical_device
784
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600785 def do_install_dhcp_flows(self, line):
786 """
787 Install all dhcp flows that are representative of the virtualized access
788 scenario in a PON network.
789 """
790 logical_device_id = line or self.default_logical_device_id
791
792 # gather NNI and UNI port IDs
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800793 nni_port_no, unis = self.get_logical_ports(logical_device_id)
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600794
795 # construct and push flow rules
khenaidoo108f05c2017-07-06 11:15:29 -0400796 stub = self.get_stub()
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600797
798 # Controller-bound flows
Zsolt Harasztib9a5f752017-02-11 06:07:08 -0800799 for uni_port_no, _ in unis:
800 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
801 id=logical_device_id,
802 flow_mod=mk_simple_flow_mod(
803 priority=1000,
804 match_fields=[
805 in_port(uni_port_no),
806 eth_type(0x800),
807 ip_proto(17),
808 udp_dst(67)
809 ],
810 actions=[output(ofp.OFPP_CONTROLLER)]
811 )
812 ))
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600813
814 self.poutput('success')
815
816 complete_install_dhcp_flows = VolthaCli.complete_logical_device
817
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800818 def do_delete_all_flows(self, line):
819 """
820 Remove all flows and flow groups from given logical device
821 """
822 logical_device_id = line or self.default_logical_device_id
khenaidoo108f05c2017-07-06 11:15:29 -0400823 stub = self.get_stub()
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800824 stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
825 id=logical_device_id,
826 flow_mod=ofp.ofp_flow_mod(
827 command=ofp.OFPFC_DELETE,
828 table_id=ofp.OFPTT_ALL,
829 cookie_mask=0,
830 out_port=ofp.OFPP_ANY,
831 out_group=ofp.OFPG_ANY
832 )
833 ))
834 stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
835 id=logical_device_id,
836 group_mod=ofp.ofp_group_mod(
837 command=ofp.OFPGC_DELETE,
838 group_id=ofp.OFPG_ALL
839 )
840 ))
841 self.poutput('success')
842
843 complete_delete_all_flows = VolthaCli.complete_logical_device
844
Zsolt Haraszti80175202016-12-24 00:17:51 -0800845 def do_send_simulated_upstream_eapol(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800846 """
847 Send an EAPOL upstream from a simulated OLT
848 """
Zsolt Haraszti80175202016-12-24 00:17:51 -0800849 device_id = line or self.default_device_id
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800850 requests.get('http://{}/devices/{}/test_eapol_in'.format(
851 self.voltha_sim_rest, device_id
852 ))
853
Zsolt Haraszti80175202016-12-24 00:17:51 -0800854 complete_send_simulated_upstream_eapol = VolthaCli.complete_device
855
856 def do_inject_eapol_start(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800857 """
858 Send out an an EAPOL start message into the given Unix interface
859 """
860 pass
Zsolt Harasztia133a452016-12-22 01:26:57 -0800861
862
863if __name__ == '__main__':
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -0800864
865 parser = argparse.ArgumentParser()
866
867 _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
868 parser.add_argument(
869 '-C', '--consul', action='store', default=defs['consul'], help=_help)
870
871 _help = 'Lookup Voltha endpoints based on service entries in Consul'
872 parser.add_argument(
873 '-L', '--lookup', action='store_true', help=_help)
874
khenaidoo108f05c2017-07-06 11:15:29 -0400875 _help = 'All requests to the Voltha gRPC service are global'
876 parser.add_argument(
877 '-G', '--global_request', action='store_true', help=_help)
878
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -0800879 _help = '<hostname>:<port> of Voltha gRPC service (default={})'.format(
880 defs['voltha_grpc_endpoint'])
881 parser.add_argument('-g', '--grpc-endpoint', action='store',
882 default=defs['voltha_grpc_endpoint'], help=_help)
883
884 _help = '<hostname>:<port> of Voltha simulated adapter backend for ' \
885 'testing (default={})'.format(
886 defs['voltha_sim_rest_endpoint'])
887 parser.add_argument('-s', '--sim-rest-endpoint', action='store',
888 default=defs['voltha_sim_rest_endpoint'], help=_help)
889
890 args = parser.parse_args()
891
892 if args.lookup:
893 host = args.consul.split(':')[0].strip()
894 port = int(args.consul.split(':')[1].strip())
895 consul = Consul(host=host, port=port)
896
897 _, services = consul.catalog.service('voltha-grpc')
898 if not services:
899 print('No voltha-grpc service registered in consul; exiting')
900 sys.exit(1)
901 args.grpc_endpoint = '{}:{}'.format(services[0]['ServiceAddress'],
902 services[0]['ServicePort'])
903
904 _, services = consul.catalog.service('voltha-sim-rest')
905 if not services:
906 print('No voltha-sim-rest service registered in consul; exiting')
907 sys.exit(1)
908 args.sim_rest_endpoint = '{}:{}'.format(services[0]['ServiceAddress'],
909 services[0]['ServicePort'])
910
khenaidoo108f05c2017-07-06 11:15:29 -0400911 c = VolthaCli(args.grpc_endpoint, args.sim_rest_endpoint,
912 args.global_request)
Zsolt Haraszti80175202016-12-24 00:17:51 -0800913 c.poutput(banner)
Zsolt Harasztia133a452016-12-22 01:26:57 -0800914 c.load_history()
915 c.cmdloop()
916 c.save_history()