blob: 8b25d22613646dce61fd643a6c82a4b4e3c6ba9b [file] [log] [blame]
Jon Hallca319892017-06-15 15:25:22 -07001#!/usr/bin/env python
2"""
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003Copyright 2017 Open Networking Foundation (ONF)
Jon Hallca319892017-06-15 15:25:22 -07004
5Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
6the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
7or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
8
9 TestON is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 2 of the License, or
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000012 (at your option) any later version.
Jon Hallca319892017-06-15 15:25:22 -070013
14 TestON is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with TestON. If not, see <http://www.gnu.org/licenses/>.
21
22
23This driver is used to interact with an ONOS cluster. It should
24handle creating the necessary components to interact with each specific ONOS nodes.
25
26Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
27the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
28or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
29
30"""
31import pexpect
32import os
33from drivers.common.clidriver import CLI
34
35# FIXME: Move this to it's own file?
36class Controller():
Jeremy Ronquillo82705492017-10-18 14:19:55 -070037
Jon Hallca319892017-06-15 15:25:22 -070038 def __str__( self ):
39 return self.name
Jeremy Ronquillo82705492017-10-18 14:19:55 -070040
Jon Hallca319892017-06-15 15:25:22 -070041 def __repr__( self ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070042 # TODO use repr() for components?
Jon Hallca319892017-06-15 15:25:22 -070043 return "%s<IP=%s, CLI=%s, REST=%s, Bench=%s >" % ( self.name,
Jon Hall4173b242017-09-12 17:04:38 -070044 self.ipAddress,
45 self.CLI,
46 self.REST,
47 self.Bench )
Jon Hallca319892017-06-15 15:25:22 -070048
49 def __getattr__( self, name ):
50 """
51 Called when an attribute lookup has not found the attribute
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000052 in the usual places (i.e. it is not an instance attribute nor
53 is it found in the class tree for self). name is the attribute
54 name. This method should return the (computed) attribute value
Jon Hallca319892017-06-15 15:25:22 -070055 or raise an AttributeError exception.
56
Daniele Moroc9b4afe2021-08-26 18:07:01 +020057 We will look into each of the node's component handles to try to find the attribute, looking at REST first
Jon Hallca319892017-06-15 15:25:22 -070058 """
59 if hasattr( self.REST, name ):
Jon Hall3c0114c2020-08-11 15:07:42 -070060 main.log.debug( "%s: Using Rest driver's attribute for '%s'" % ( self.name, name ) )
61 return getattr( self.REST, name )
Jon Hallca319892017-06-15 15:25:22 -070062 if hasattr( self.CLI, name ):
Jon Hall3c0114c2020-08-11 15:07:42 -070063 main.log.debug( "%s: Using CLI driver's attribute for '%s'" % ( self.name, name ) )
64 return getattr( self.CLI, name )
Jon Hallca319892017-06-15 15:25:22 -070065 if hasattr( self.Bench, name ):
Jon Hall3c0114c2020-08-11 15:07:42 -070066 main.log.debug( "%s: Using Bench driver's attribute for '%s'" % ( self.name, name ) )
67 return getattr( self.Bench, name )
Daniele Moroc9b4afe2021-08-26 18:07:01 +020068 if hasattr( self.p4rtUp4, name ):
69 main.log.debug( "%s: Using UP4 driver's attribute for '%s'" % ( self.name, name ) )
70 return getattr( self.p4rtUp4, name )
Devin Lim142b5342017-07-20 15:22:39 -070071 raise AttributeError( "Could not find the attribute %s in %r or it's component handles" % ( name, self ) )
Jon Hallca319892017-06-15 15:25:22 -070072
Jon Hall3c0114c2020-08-11 15:07:42 -070073 def __init__( self, name, ipAddress, CLI=None, REST=None, Bench=None, pos=None,
Daniele Moroc9b4afe2021-08-26 18:07:01 +020074 userName=None, server=None, k8s=None, p4rtUp4=None, dockerPrompt=None ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070075 # TODO: validate these arguments
Jon Hallca319892017-06-15 15:25:22 -070076 self.name = str( name )
77 self.ipAddress = ipAddress
78 self.CLI = CLI
79 self.REST = REST
80 self.Bench = Bench
81 self.active = False
Devin Lim142b5342017-07-20 15:22:39 -070082 self.pos = pos
83 self.ip_address = ipAddress
84 self.user_name = userName
Jon Hall4173b242017-09-12 17:04:38 -070085 self.server = server
Jon Hall06fd0df2021-01-25 15:50:06 -080086 self.k8s = k8s
Daniele Moroc9b4afe2021-08-26 18:07:01 +020087 self.p4rtUp4 = p4rtUp4
Jon Hall3c0114c2020-08-11 15:07:42 -070088 self.dockerPrompt = dockerPrompt
Jon Hallca319892017-06-15 15:25:22 -070089
90class OnosClusterDriver( CLI ):
91
92 def __init__( self ):
93 """
94 Initialize client
95 """
96 self.name = None
97 self.home = None
98 self.handle = None
Jon Hall3c0114c2020-08-11 15:07:42 -070099 self.useDocker = False
100 self.dockerPrompt = None
Jon Halle37bd1f2020-09-10 12:16:41 -0700101 self.maxNodes = None
Siddesh52750622021-03-05 19:52:03 +0000102 self.karafPromptPass = None
Jon Hall06fd0df2021-01-25 15:50:06 -0800103 self.kubeConfig = None
Siddesh52750622021-03-05 19:52:03 +0000104 self.karafPromptUser = None
Jon Hall3a03cad2021-04-07 11:21:55 -0700105 self.nodeUser = None
106 self.nodePass = None
Jon Hallca319892017-06-15 15:25:22 -0700107 self.nodes = []
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200108 self.up4Port = None
Jon Hallca319892017-06-15 15:25:22 -0700109 super( OnosClusterDriver, self ).__init__()
110
Jon Hallca319892017-06-15 15:25:22 -0700111 def connect( self, **connectargs ):
112 """
113 Creates ssh handle for ONOS "bench".
114 NOTE:
115 The ip_address would come from the topo file using the host tag, the
116 value can be an environment variable as well as a "localhost" to get
117 the ip address needed to ssh to the "bench"
118 """
119 try:
120 for key in connectargs:
121 vars( self )[ key ] = connectargs[ key ]
122 self.home = "~/onos"
123 for key in self.options:
124 if key == "home":
Jon Halle37bd1f2020-09-10 12:16:41 -0700125 self.home = self.options[ key ]
Jon Hallca319892017-06-15 15:25:22 -0700126 elif key == "karaf_username":
127 self.karafUser = self.options[ key ]
128 elif key == "karaf_password":
129 self.karafPass = self.options[ key ]
Siddesh52750622021-03-05 19:52:03 +0000130 elif key == "node_username":
131 self.nodeUser = self.options[ key ]
132 elif key == "node_password":
133 self.nodePass = self.options[ key ]
134 elif key == "karafPrompt_username":
135 self.karafPromptUser = self.options[ key ]
136 elif key == "karafPrompt_password":
137 self.karafPromptPass = self.options[ key ]
Jon Hallca319892017-06-15 15:25:22 -0700138 elif key == "cluster_name":
139 prefix = self.options[ key ]
Jon Hall3c0114c2020-08-11 15:07:42 -0700140 elif key == "useDocker":
141 self.useDocker = "True" == self.options[ key ]
142 elif key == "docker_prompt":
143 self.dockerPrompt = self.options[ key ]
Jon Hall9b0de1f2020-08-24 15:38:04 -0700144 elif key == "web_user":
145 self.webUser = self.options[ key ]
146 elif key == "web_pass":
147 self.webPass = self.options[ key ]
Jon Halle37bd1f2020-09-10 12:16:41 -0700148 elif key == "nodes":
149 # Maximum number of ONOS nodes to run, if there is any
150 self.maxNodes = self.options[ key ]
Jon Hall06fd0df2021-01-25 15:50:06 -0800151 elif key == "kubeConfig":
152 self.kubeConfig = self.options[ key ]
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200153 elif key == "up4_port":
154 # Defining up4_port triggers the creation of the P4RuntimeCliDriver component
155 self.up4Port = self.options[ key ]
Jon Hallca319892017-06-15 15:25:22 -0700156
Jon Hall0e240372018-05-02 11:21:57 -0700157 self.home = self.checkOptions( self.home, "~/onos" )
158 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
159 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
Siddesh52750622021-03-05 19:52:03 +0000160 self.nodeUser = self.checkOptions( self.nodeUser, self.user_name )
161 self.nodePass = self.checkOptions( self.nodePass, self.pwd )
162 self.karafPromptUser = self.checkOptions( self.karafPromptUser, self.user_name )
163 self.karafPromptPass = self.checkOptions( self.karafPromptPass, self.pwd )
Jon Hall9b0de1f2020-08-24 15:38:04 -0700164 self.webUser = self.checkOptions( self.webUser, "onos" )
165 self.webPass = self.checkOptions( self.webPass, "rocks" )
Jon Hallca319892017-06-15 15:25:22 -0700166 prefix = self.checkOptions( prefix, "ONOS" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700167 self.useDocker = self.checkOptions( self.useDocker, False )
168 self.dockerPrompt = self.checkOptions( self.dockerPrompt, "~/onos#" )
Jon Halle37bd1f2020-09-10 12:16:41 -0700169 self.maxNodes = int( self.checkOptions( self.maxNodes, 100 ) )
Jon Hall06fd0df2021-01-25 15:50:06 -0800170 self.kubeConfig = self.checkOptions( self.kubeConfig, None )
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200171 self.up4Port = self.checkOptions(self.up4Port, None)
Jon Hallca319892017-06-15 15:25:22 -0700172
173 self.name = self.options[ 'name' ]
174
Jon Hallca319892017-06-15 15:25:22 -0700175
Jon Hall06fd0df2021-01-25 15:50:06 -0800176 if not self.kubeConfig:
177 # Grabs all OC environment variables based on max number of nodes
178 # TODO: Also support giving an ip range as a compononet option
179 self.onosIps = {} # Dictionary of all possible ONOS ip
180
181 try:
182 if self.maxNodes:
183 for i in range( self.maxNodes ):
184 envString = "OC" + str( i + 1 )
185 # If there is no more OC# then break the loop
186 if os.getenv( envString ):
187 self.onosIps[ envString ] = os.getenv( envString )
188 else:
189 self.maxNodes = len( self.onosIps )
190 main.log.info( self.name +
191 ": Created cluster data with " +
192 str( self.maxNodes ) +
193 " maximum number" +
194 " of nodes" )
195 break
196
197 if not self.onosIps:
198 main.log.info( "Could not read any environment variable"
199 + " please load a cell file with all" +
200 " onos IP" )
201 self.maxNodes = None
Jon Hallca319892017-06-15 15:25:22 -0700202 else:
Jon Hall06fd0df2021-01-25 15:50:06 -0800203 main.log.info( self.name + ": Found " +
204 str( self.onosIps.values() ) +
205 " ONOS IPs" )
206 except KeyError:
207 main.log.info( "Invalid environment variable" )
208 except Exception as inst:
209 main.log.error( "Uncaught exception: " + str( inst ) )
Jon Hallca319892017-06-15 15:25:22 -0700210 try:
211 if os.getenv( str( self.ip_address ) ) is not None:
212 self.ip_address = os.getenv( str( self.ip_address ) )
213 else:
214 main.log.info( self.name +
215 ": Trying to connect to " +
216 self.ip_address )
217 except KeyError:
218 main.log.info( "Invalid host name," +
219 " connecting to local host instead" )
220 self.ip_address = 'localhost'
221 except Exception as inst:
222 main.log.error( "Uncaught exception: " + str( inst ) )
223
224 self.handle = super( OnosClusterDriver, self ).connect(
225 user_name=self.user_name,
226 ip_address=self.ip_address,
227 port=self.port,
228 pwd=self.pwd,
229 home=self.home )
230
231 if self.handle:
232 self.handle.sendline( "cd " + self.home )
233 self.handle.expect( "\$" )
Jon Hall06fd0df2021-01-25 15:50:06 -0800234 if self.kubeConfig:
235 # Try to get # of onos nodes using given kubernetes configuration
236 names = self.kubectlGetPodNames( self.kubeConfig,
237 main.params[ 'kubernetes' ][ 'namespace' ],
238 main.params[ 'kubernetes' ][ 'appName' ] )
239 self.podNames = names
240 self.onosIps = {} # Dictionary of all possible ONOS ip
241 for i in range( 1, len( names ) + 1 ):
242 self.onosIps[ 'OC%i' % i ] = self.ip_address
243 self.maxNodes = len( names )
Jon Hallca319892017-06-15 15:25:22 -0700244 self.createComponents( prefix=prefix )
Jon Hall06fd0df2021-01-25 15:50:06 -0800245 if self.kubeConfig:
246 # Create Port Forwarding sessions for each controller
247 for node in self.nodes:
248 kubectl = node.k8s
249 index = self.nodes.index( node )
250 # Store each pod name in the k8s component
251 kubectl.podName = self.podNames[ index ]
252 # Setup port-forwarding and save the local port
253 guiPort = 8181
254 cliPort = 8101
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200255 fwdPorts = [ guiPort, cliPort ]
256 if self.up4Port:
257 fwdPorts.append( int( self.up4Port ) )
Jon Hall06fd0df2021-01-25 15:50:06 -0800258 portsList = ""
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200259 for port in fwdPorts:
Jon Hall06fd0df2021-01-25 15:50:06 -0800260 localPort = port + index + 1
261 portsList += "%s:%s " % ( localPort, port )
262 if port == cliPort:
263 node.CLI.karafPort = localPort
Jon Hall50a00012021-03-08 11:06:11 -0800264 elif port == guiPort:
265 node.REST.port = localPort
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200266 elif self.up4Port and port == int( self.up4Port ):
267 node.p4rtUp4.p4rtPort = localPort
Jon Hall06fd0df2021-01-25 15:50:06 -0800268 main.log.info( "Setting up port forward for pod %s: [ %s ]" % ( self.podNames[ index ], portsList ) )
269 pf = kubectl.kubectlPortForward( self.podNames[ index ],
270 portsList,
271 kubectl.kubeConfig,
272 main.params[ 'kubernetes' ][ 'namespace' ] )
273 if not pf:
274 main.log.error( "Failed to create port forwarding" )
275 return main.FALSE
Jon Hallca319892017-06-15 15:25:22 -0700276 return self.handle
277 else:
278 main.log.info( "Failed to create ONOS handle" )
279 return main.FALSE
280 except pexpect.EOF:
281 main.log.error( self.name + ": EOF exception found" )
282 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700283 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700284 except Exception:
285 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700286 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700287
288 def disconnect( self ):
289 """
290 Called when Test is complete to disconnect the ONOS handle.
291 """
292 response = main.TRUE
293 try:
294 if self.handle:
295 self.handle.sendline( "" )
296 self.handle.expect( "\$" )
297 self.handle.sendline( "exit" )
298 self.handle.expect( "closed" )
299 except pexpect.EOF:
300 main.log.error( self.name + ": EOF exception found" )
301 main.log.error( self.name + ": " + self.handle.before )
302 except ValueError:
303 main.log.exception( "Exception in disconnect of " + self.name )
304 response = main.TRUE
305 except Exception:
306 main.log.exception( self.name + ": Connection failed to the host" )
307 response = main.FALSE
308 return response
309
Devin Lim142b5342017-07-20 15:22:39 -0700310 def setCliOptions( self, name, host ):
Jon Hallca319892017-06-15 15:25:22 -0700311 """
312 Parse the cluster options to create an ONOS cli component with the given name
313 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000314 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
Devin Lim142b5342017-07-20 15:22:39 -0700315 clihost = main.componentDictionary[ name ][ 'COMPONENTS' ].get( "diff_clihost", "" )
316 if clihost == "True":
317 main.componentDictionary[ name ][ 'host' ] = host
Jon Hall06fd0df2021-01-25 15:50:06 -0800318 home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
319 main.componentDictionary[name]['home'] = self.checkOptions( home, None )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000320 main.componentDictionary[name]['type'] = "OnosCliDriver"
Siddesh52750622021-03-05 19:52:03 +0000321 main.componentDictionary[name]['COMPONENTS']['karafPromptUser'] = self.karafPromptUser
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000322 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hallca319892017-06-15 15:25:22 -0700323
Devin Lim142b5342017-07-20 15:22:39 -0700324 def createCliComponent( self, name, host ):
Jon Hallca319892017-06-15 15:25:22 -0700325 """
326 Creates a new onos cli component.
327
328 Arguments:
329 name - The string of the name of this component. The new component
330 will be assigned to main.<name> .
331 In addition, main.<name>.name = str( name )
332 """
333 try:
334 # look to see if this component already exists
335 getattr( main, name )
336 except AttributeError:
337 # namespace is clear, creating component
Devin Lim142b5342017-07-20 15:22:39 -0700338 self.setCliOptions( name, host )
Jon Hallca319892017-06-15 15:25:22 -0700339 return main.componentInit( name )
340 except pexpect.EOF:
341 main.log.error( self.name + ": EOF exception found" )
342 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700343 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700344 except Exception:
345 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700346 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700347 else:
348 # namespace is not clear!
349 main.log.error( name + " component already exists!" )
Devin Lim44075962017-08-11 10:56:37 -0700350 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700351
352 def setRestOptions( self, name, host ):
353 """
354 Parse the cluster options to create an ONOS cli component with the given name
355 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000356 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000357 user = main.componentDictionary[name]['COMPONENTS'].get( "web_user", "onos" )
358 main.componentDictionary[name]['user'] = self.checkOptions( user, "onos" )
359 password = main.componentDictionary[name]['COMPONENTS'].get( "web_pass", "rocks" )
You Wangbef7ea12018-09-21 13:15:12 -0700360 main.componentDictionary[name]['password'] = self.checkOptions( password, "rocks" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000361 main.componentDictionary[name]['host'] = host
362 port = main.componentDictionary[name]['COMPONENTS'].get( "rest_port", "8181" )
363 main.componentDictionary[name]['port'] = self.checkOptions( port, "8181" )
364 main.componentDictionary[name]['type'] = "OnosRestDriver"
365 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hallca319892017-06-15 15:25:22 -0700366
367 def createRestComponent( self, name, ipAddress ):
368 """
369 Creates a new onos rest component.
370
371 Arguments:
372 name - The string of the name of this component. The new component
373 will be assigned to main.<name> .
374 In addition, main.<name>.name = str( name )
375 """
376 try:
377 # look to see if this component already exists
378 getattr( main, name )
379 except AttributeError:
380 # namespace is clear, creating component
381 self.setRestOptions( name, ipAddress )
382 return main.componentInit( name )
383 except pexpect.EOF:
384 main.log.error( self.name + ": EOF exception found" )
385 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700386 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700387 except Exception:
388 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700389 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700390 else:
391 # namespace is not clear!
392 main.log.error( name + " component already exists!" )
Devin Lim44075962017-08-11 10:56:37 -0700393 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700394
395 def setBenchOptions( self, name ):
396 """
397 Parse the cluster options to create an ONOS "bench" component with the given name
398 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000399 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
400 main.componentDictionary[name]['type'] = "OnosDriver"
401 home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
402 main.componentDictionary[name]['home'] = self.checkOptions( home, None )
403 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hallca319892017-06-15 15:25:22 -0700404
405 def createBenchComponent( self, name ):
406 """
407 Creates a new onos "bench" component.
408
409 Arguments:
410 name - The string of the name of this component. The new component
411 will be assigned to main.<name> .
412 In addition, main.<name>.name = str( name )
413 """
414 try:
415 # look to see if this component already exists
416 getattr( main, name )
417 except AttributeError:
418 # namespace is clear, creating component
419 self.setBenchOptions( name )
420 return main.componentInit( name )
421 except pexpect.EOF:
422 main.log.error( self.name + ": EOF exception found" )
423 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700424 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700425 except Exception:
426 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700427 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700428 else:
429 # namespace is not clear!
430 main.log.error( name + " component already exists!" )
Devin Lim44075962017-08-11 10:56:37 -0700431 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700432
Jon Hall4173b242017-09-12 17:04:38 -0700433 def setServerOptions( self, name, ipAddress ):
434 """
435 Parse the cluster options to create an ONOS "server" component with the given name
436
437 Arguments:
438 name - The name of the server componet
439 ipAddress - The ip address of the server
440 """
441 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
442 main.componentDictionary[name]['type'] = "OnosDriver"
443 main.componentDictionary[name]['host'] = ipAddress
444 home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
445 main.componentDictionary[name]['home'] = self.checkOptions( home, None )
You Wang4cc61912018-08-28 10:10:58 -0700446 # TODO: for now we use karaf user name and password also for logging to the onos nodes
Jon Hall06fd0df2021-01-25 15:50:06 -0800447 # FIXME: We shouldn't use karaf* for this, what we want is another set of variables to
448 # login to a shell on the server ONOS is running on
Siddesh52750622021-03-05 19:52:03 +0000449 main.componentDictionary[name]['user'] = self.nodeUser
450 main.componentDictionary[name]['password'] = self.nodePass
Jon Hall4173b242017-09-12 17:04:38 -0700451 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hall4173b242017-09-12 17:04:38 -0700452
Jon Hall4173b242017-09-12 17:04:38 -0700453 def createServerComponent( self, name, ipAddress ):
454 """
455 Creates a new onos "server" component. This will be connected to the
456 node ONOS is running on.
457
458 Arguments:
459 name - The string of the name of this component. The new component
460 will be assigned to main.<name> .
461 In addition, main.<name>.name = str( name )
462 ipAddress - The ip address of the server
463 """
464 try:
465 # look to see if this component already exists
466 getattr( main, name )
467 except AttributeError:
468 # namespace is clear, creating component
469 self.setServerOptions( name, ipAddress )
470 return main.componentInit( name )
471 except pexpect.EOF:
472 main.log.error( self.name + ": EOF exception found" )
473 main.log.error( self.name + ": " + self.handle.before )
474 main.cleanAndExit()
475 except Exception:
476 main.log.exception( self.name + ": Uncaught exception!" )
477 main.cleanAndExit()
478 else:
479 # namespace is not clear!
480 main.log.error( name + " component already exists!" )
481 main.cleanAndExit()
482
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200483 def setP4rtCLIOptions( self, name, ipAddress ):
484 """
485 Parse the cluster options to create an UP4 component with the given name
486
487 Arguments:
488 name - The name of the P4RuntimeCLI component
489 ipAddress - The ip address of the ONOS instance
490 """
491 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
492 main.componentDictionary[name]['type'] = "P4RuntimeCliDriver"
493 main.componentDictionary[name]['host'] = ipAddress
494 port = main.componentDictionary[name]['COMPONENTS'].get( "p4rt_port", "9559" )
495 main.componentDictionary[name]['p4rt_port'] = self.checkOptions( port, "9559" )
496 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
497
498 def createP4rtCLIComponent( self, name, ipAddress ):
499 """
500 Creates a new P4Runtime CLI component. This will be connected to the node
501 ONOS is running on.
502
503 Arguments:
504 name - The string of the name of this component. The new component
505 will be assigned to main.<name> .
506 In addition, main.<name>.name = str( name )
507 ipAddress - The ip address of the server
508 """
509 try:
510 # look to see if this component already exists
511 getattr( main, name )
512 except AttributeError:
513 # namespace is clear, creating component
514 self.setP4rtCLIOptions( name, ipAddress )
515 return main.componentInit( name )
516 except pexpect.EOF:
517 main.log.error( self.name + ": EOF exception found" )
518 main.log.error( self.name + ": " + self.handle.before )
519 main.cleanAndExit()
520 except Exception:
521 main.log.exception( self.name + ": Uncaught exception!" )
522 main.cleanAndExit()
523 else:
524 # namespace is not clear!
525 main.log.error( name + " component already exists!" )
526 main.cleanAndExit()
527
Jon Hall4173b242017-09-12 17:04:38 -0700528 def createComponents( self, prefix='', createServer=True ):
Jon Hallca319892017-06-15 15:25:22 -0700529 """
530 Creates a CLI and REST component for each nodes in the cluster
531 """
532 # TODO: This needs work to support starting two seperate clusters in one test
533 cliPrefix = prefix + "cli"
534 restPrefix = prefix + "rest"
535 benchPrefix = prefix + "bench"
Jon Hall4173b242017-09-12 17:04:38 -0700536 serverPrefix = prefix + "server"
Jon Hall06fd0df2021-01-25 15:50:06 -0800537 k8sPrefix = prefix + "k8s"
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200538 up4Prefix = prefix + "up4cl"
Jon Hallca319892017-06-15 15:25:22 -0700539 for i in xrange( 1, self.maxNodes + 1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000540 cliName = cliPrefix + str( i )
Jon Hallca319892017-06-15 15:25:22 -0700541 restName = restPrefix + str( i )
542 benchName = benchPrefix + str( i )
Jon Hall4173b242017-09-12 17:04:38 -0700543 serverName = serverPrefix + str( i )
Jon Hall06fd0df2021-01-25 15:50:06 -0800544 if self.kubeConfig:
545 k8sName = k8sPrefix + str( i )
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200546 if self.up4Port:
547 up4Name = up4Prefix + str( i )
Jon Hallca319892017-06-15 15:25:22 -0700548
549 # Unfortunately this means we need to have a cell set beofre running TestON,
550 # Even if it is just the entire possible cluster size
551 ip = self.onosIps[ 'OC' + str( i ) ]
552
Devin Lim142b5342017-07-20 15:22:39 -0700553 cli = self.createCliComponent( cliName, ip )
Jon Hallca319892017-06-15 15:25:22 -0700554 rest = self.createRestComponent( restName, ip )
555 bench = self.createBenchComponent( benchName )
Jon Hall4173b242017-09-12 17:04:38 -0700556 server = self.createServerComponent( serverName, ip ) if createServer else None
Jon Hall06fd0df2021-01-25 15:50:06 -0800557 k8s = self.createServerComponent( k8sName, ip ) if self.kubeConfig else None
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200558 p4rtUp4 = self.createP4rtCLIComponent( up4Name, ip ) if self.up4Port else None
Jon Hall06fd0df2021-01-25 15:50:06 -0800559 if self.kubeConfig:
560 k8s.kubeConfig = self.kubeConfig
561 k8s.podName = None
Jon Hall3c0114c2020-08-11 15:07:42 -0700562 self.nodes.append( Controller( prefix + str( i ), ip, cli, rest, bench, i - 1,
Jon Hall06fd0df2021-01-25 15:50:06 -0800563 self.user_name, server=server, k8s=k8s,
Daniele Moroc9b4afe2021-08-26 18:07:01 +0200564 p4rtUp4=p4rtUp4, dockerPrompt=self.dockerPrompt ) )