blob: f3de41d0c971a7ebedb490d862452572cb64a54e [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
57 We will look into each of the node's component handles to try to find the attreibute, looking at REST first
58 """
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 )
Devin Lim142b5342017-07-20 15:22:39 -070068 raise AttributeError( "Could not find the attribute %s in %r or it's component handles" % ( name, self ) )
Jon Hallca319892017-06-15 15:25:22 -070069
Jon Hall3c0114c2020-08-11 15:07:42 -070070 def __init__( self, name, ipAddress, CLI=None, REST=None, Bench=None, pos=None,
Jon Hall06fd0df2021-01-25 15:50:06 -080071 userName=None, server=None, k8s=None, dockerPrompt=None ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070072 # TODO: validate these arguments
Jon Hallca319892017-06-15 15:25:22 -070073 self.name = str( name )
74 self.ipAddress = ipAddress
75 self.CLI = CLI
76 self.REST = REST
77 self.Bench = Bench
78 self.active = False
Devin Lim142b5342017-07-20 15:22:39 -070079 self.pos = pos
80 self.ip_address = ipAddress
81 self.user_name = userName
Jon Hall4173b242017-09-12 17:04:38 -070082 self.server = server
Jon Hall06fd0df2021-01-25 15:50:06 -080083 self.k8s = k8s
Jon Hall3c0114c2020-08-11 15:07:42 -070084 self.dockerPrompt = dockerPrompt
Jon Hallca319892017-06-15 15:25:22 -070085
86class OnosClusterDriver( CLI ):
87
88 def __init__( self ):
89 """
90 Initialize client
91 """
92 self.name = None
93 self.home = None
94 self.handle = None
Jon Hall3c0114c2020-08-11 15:07:42 -070095 self.useDocker = False
96 self.dockerPrompt = None
Jon Halle37bd1f2020-09-10 12:16:41 -070097 self.maxNodes = None
Siddesh52750622021-03-05 19:52:03 +000098 self.karafPromptPass = None
Jon Hall06fd0df2021-01-25 15:50:06 -080099 self.kubeConfig = None
Siddesh52750622021-03-05 19:52:03 +0000100 self.karafPromptUser = None
Jon Hallca319892017-06-15 15:25:22 -0700101 self.nodes = []
102 super( OnosClusterDriver, self ).__init__()
103
Jon Hallca319892017-06-15 15:25:22 -0700104 def connect( self, **connectargs ):
105 """
106 Creates ssh handle for ONOS "bench".
107 NOTE:
108 The ip_address would come from the topo file using the host tag, the
109 value can be an environment variable as well as a "localhost" to get
110 the ip address needed to ssh to the "bench"
111 """
112 try:
113 for key in connectargs:
114 vars( self )[ key ] = connectargs[ key ]
115 self.home = "~/onos"
116 for key in self.options:
117 if key == "home":
Jon Halle37bd1f2020-09-10 12:16:41 -0700118 self.home = self.options[ key ]
Jon Hallca319892017-06-15 15:25:22 -0700119 elif key == "karaf_username":
120 self.karafUser = self.options[ key ]
121 elif key == "karaf_password":
122 self.karafPass = self.options[ key ]
Siddesh52750622021-03-05 19:52:03 +0000123 elif key == "node_username":
124 self.nodeUser = self.options[ key ]
125 elif key == "node_password":
126 self.nodePass = self.options[ key ]
127 elif key == "karafPrompt_username":
128 self.karafPromptUser = self.options[ key ]
129 elif key == "karafPrompt_password":
130 self.karafPromptPass = self.options[ key ]
Jon Hallca319892017-06-15 15:25:22 -0700131 elif key == "cluster_name":
132 prefix = self.options[ key ]
Jon Hall3c0114c2020-08-11 15:07:42 -0700133 elif key == "useDocker":
134 self.useDocker = "True" == self.options[ key ]
135 elif key == "docker_prompt":
136 self.dockerPrompt = self.options[ key ]
Jon Hall9b0de1f2020-08-24 15:38:04 -0700137 elif key == "web_user":
138 self.webUser = self.options[ key ]
139 elif key == "web_pass":
140 self.webPass = self.options[ key ]
Jon Halle37bd1f2020-09-10 12:16:41 -0700141 elif key == "nodes":
142 # Maximum number of ONOS nodes to run, if there is any
143 self.maxNodes = self.options[ key ]
Jon Hall06fd0df2021-01-25 15:50:06 -0800144 elif key == "kubeConfig":
145 self.kubeConfig = self.options[ key ]
Jon Hallca319892017-06-15 15:25:22 -0700146
Jon Hall0e240372018-05-02 11:21:57 -0700147 self.home = self.checkOptions( self.home, "~/onos" )
148 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
149 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
Siddesh52750622021-03-05 19:52:03 +0000150 self.nodeUser = self.checkOptions( self.nodeUser, self.user_name )
151 self.nodePass = self.checkOptions( self.nodePass, self.pwd )
152 self.karafPromptUser = self.checkOptions( self.karafPromptUser, self.user_name )
153 self.karafPromptPass = self.checkOptions( self.karafPromptPass, self.pwd )
Jon Hall9b0de1f2020-08-24 15:38:04 -0700154 self.webUser = self.checkOptions( self.webUser, "onos" )
155 self.webPass = self.checkOptions( self.webPass, "rocks" )
Jon Hallca319892017-06-15 15:25:22 -0700156 prefix = self.checkOptions( prefix, "ONOS" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700157 self.useDocker = self.checkOptions( self.useDocker, False )
158 self.dockerPrompt = self.checkOptions( self.dockerPrompt, "~/onos#" )
Jon Halle37bd1f2020-09-10 12:16:41 -0700159 self.maxNodes = int( self.checkOptions( self.maxNodes, 100 ) )
Jon Hall06fd0df2021-01-25 15:50:06 -0800160 self.kubeConfig = self.checkOptions( self.kubeConfig, None )
Jon Hallca319892017-06-15 15:25:22 -0700161
162 self.name = self.options[ 'name' ]
163
Jon Hallca319892017-06-15 15:25:22 -0700164
Jon Hall06fd0df2021-01-25 15:50:06 -0800165 if not self.kubeConfig:
166 # Grabs all OC environment variables based on max number of nodes
167 # TODO: Also support giving an ip range as a compononet option
168 self.onosIps = {} # Dictionary of all possible ONOS ip
169
170 try:
171 if self.maxNodes:
172 for i in range( self.maxNodes ):
173 envString = "OC" + str( i + 1 )
174 # If there is no more OC# then break the loop
175 if os.getenv( envString ):
176 self.onosIps[ envString ] = os.getenv( envString )
177 else:
178 self.maxNodes = len( self.onosIps )
179 main.log.info( self.name +
180 ": Created cluster data with " +
181 str( self.maxNodes ) +
182 " maximum number" +
183 " of nodes" )
184 break
185
186 if not self.onosIps:
187 main.log.info( "Could not read any environment variable"
188 + " please load a cell file with all" +
189 " onos IP" )
190 self.maxNodes = None
Jon Hallca319892017-06-15 15:25:22 -0700191 else:
Jon Hall06fd0df2021-01-25 15:50:06 -0800192 main.log.info( self.name + ": Found " +
193 str( self.onosIps.values() ) +
194 " ONOS IPs" )
195 except KeyError:
196 main.log.info( "Invalid environment variable" )
197 except Exception as inst:
198 main.log.error( "Uncaught exception: " + str( inst ) )
Jon Hallca319892017-06-15 15:25:22 -0700199 try:
200 if os.getenv( str( self.ip_address ) ) is not None:
201 self.ip_address = os.getenv( str( self.ip_address ) )
202 else:
203 main.log.info( self.name +
204 ": Trying to connect to " +
205 self.ip_address )
206 except KeyError:
207 main.log.info( "Invalid host name," +
208 " connecting to local host instead" )
209 self.ip_address = 'localhost'
210 except Exception as inst:
211 main.log.error( "Uncaught exception: " + str( inst ) )
212
213 self.handle = super( OnosClusterDriver, self ).connect(
214 user_name=self.user_name,
215 ip_address=self.ip_address,
216 port=self.port,
217 pwd=self.pwd,
218 home=self.home )
219
220 if self.handle:
221 self.handle.sendline( "cd " + self.home )
222 self.handle.expect( "\$" )
Jon Hall06fd0df2021-01-25 15:50:06 -0800223 if self.kubeConfig:
224 # Try to get # of onos nodes using given kubernetes configuration
225 names = self.kubectlGetPodNames( self.kubeConfig,
226 main.params[ 'kubernetes' ][ 'namespace' ],
227 main.params[ 'kubernetes' ][ 'appName' ] )
228 self.podNames = names
229 self.onosIps = {} # Dictionary of all possible ONOS ip
230 for i in range( 1, len( names ) + 1 ):
231 self.onosIps[ 'OC%i' % i ] = self.ip_address
232 self.maxNodes = len( names )
Jon Hallca319892017-06-15 15:25:22 -0700233 self.createComponents( prefix=prefix )
Jon Hall06fd0df2021-01-25 15:50:06 -0800234 if self.kubeConfig:
235 # Create Port Forwarding sessions for each controller
236 for node in self.nodes:
237 kubectl = node.k8s
238 index = self.nodes.index( node )
239 # Store each pod name in the k8s component
240 kubectl.podName = self.podNames[ index ]
241 # Setup port-forwarding and save the local port
242 guiPort = 8181
243 cliPort = 8101
244 portsList = ""
245 for port in [ guiPort, cliPort ]:
246 localPort = port + index + 1
247 portsList += "%s:%s " % ( localPort, port )
248 if port == cliPort:
249 node.CLI.karafPort = localPort
Jon Hall50a00012021-03-08 11:06:11 -0800250 elif port == guiPort:
251 node.REST.port = localPort
Jon Hall06fd0df2021-01-25 15:50:06 -0800252 main.log.info( "Setting up port forward for pod %s: [ %s ]" % ( self.podNames[ index ], portsList ) )
253 pf = kubectl.kubectlPortForward( self.podNames[ index ],
254 portsList,
255 kubectl.kubeConfig,
256 main.params[ 'kubernetes' ][ 'namespace' ] )
257 if not pf:
258 main.log.error( "Failed to create port forwarding" )
259 return main.FALSE
Jon Hallca319892017-06-15 15:25:22 -0700260 return self.handle
261 else:
262 main.log.info( "Failed to create ONOS handle" )
263 return main.FALSE
264 except pexpect.EOF:
265 main.log.error( self.name + ": EOF exception found" )
266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700267 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700268 except Exception:
269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700270 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700271
272 def disconnect( self ):
273 """
274 Called when Test is complete to disconnect the ONOS handle.
275 """
276 response = main.TRUE
277 try:
278 if self.handle:
279 self.handle.sendline( "" )
280 self.handle.expect( "\$" )
281 self.handle.sendline( "exit" )
282 self.handle.expect( "closed" )
283 except pexpect.EOF:
284 main.log.error( self.name + ": EOF exception found" )
285 main.log.error( self.name + ": " + self.handle.before )
286 except ValueError:
287 main.log.exception( "Exception in disconnect of " + self.name )
288 response = main.TRUE
289 except Exception:
290 main.log.exception( self.name + ": Connection failed to the host" )
291 response = main.FALSE
292 return response
293
Devin Lim142b5342017-07-20 15:22:39 -0700294 def setCliOptions( self, name, host ):
Jon Hallca319892017-06-15 15:25:22 -0700295 """
296 Parse the cluster options to create an ONOS cli component with the given name
297 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000298 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
Devin Lim142b5342017-07-20 15:22:39 -0700299 clihost = main.componentDictionary[ name ][ 'COMPONENTS' ].get( "diff_clihost", "" )
300 if clihost == "True":
301 main.componentDictionary[ name ][ 'host' ] = host
Jon Hall06fd0df2021-01-25 15:50:06 -0800302 home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
303 main.componentDictionary[name]['home'] = self.checkOptions( home, None )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000304 main.componentDictionary[name]['type'] = "OnosCliDriver"
Siddesh52750622021-03-05 19:52:03 +0000305 main.componentDictionary[name]['COMPONENTS']['karafPromptUser'] = self.karafPromptUser
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000306 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hallca319892017-06-15 15:25:22 -0700307
Devin Lim142b5342017-07-20 15:22:39 -0700308 def createCliComponent( self, name, host ):
Jon Hallca319892017-06-15 15:25:22 -0700309 """
310 Creates a new onos cli component.
311
312 Arguments:
313 name - The string of the name of this component. The new component
314 will be assigned to main.<name> .
315 In addition, main.<name>.name = str( name )
316 """
317 try:
318 # look to see if this component already exists
319 getattr( main, name )
320 except AttributeError:
321 # namespace is clear, creating component
Devin Lim142b5342017-07-20 15:22:39 -0700322 self.setCliOptions( name, host )
Jon Hallca319892017-06-15 15:25:22 -0700323 return main.componentInit( name )
324 except pexpect.EOF:
325 main.log.error( self.name + ": EOF exception found" )
326 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700327 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700328 except Exception:
329 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700330 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700331 else:
332 # namespace is not clear!
333 main.log.error( name + " component already exists!" )
Devin Lim44075962017-08-11 10:56:37 -0700334 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700335
336 def setRestOptions( self, name, host ):
337 """
338 Parse the cluster options to create an ONOS cli component with the given name
339 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000340 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000341 user = main.componentDictionary[name]['COMPONENTS'].get( "web_user", "onos" )
342 main.componentDictionary[name]['user'] = self.checkOptions( user, "onos" )
343 password = main.componentDictionary[name]['COMPONENTS'].get( "web_pass", "rocks" )
You Wangbef7ea12018-09-21 13:15:12 -0700344 main.componentDictionary[name]['password'] = self.checkOptions( password, "rocks" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000345 main.componentDictionary[name]['host'] = host
346 port = main.componentDictionary[name]['COMPONENTS'].get( "rest_port", "8181" )
347 main.componentDictionary[name]['port'] = self.checkOptions( port, "8181" )
348 main.componentDictionary[name]['type'] = "OnosRestDriver"
349 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hallca319892017-06-15 15:25:22 -0700350
351 def createRestComponent( self, name, ipAddress ):
352 """
353 Creates a new onos rest component.
354
355 Arguments:
356 name - The string of the name of this component. The new component
357 will be assigned to main.<name> .
358 In addition, main.<name>.name = str( name )
359 """
360 try:
361 # look to see if this component already exists
362 getattr( main, name )
363 except AttributeError:
364 # namespace is clear, creating component
365 self.setRestOptions( name, ipAddress )
366 return main.componentInit( name )
367 except pexpect.EOF:
368 main.log.error( self.name + ": EOF exception found" )
369 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700370 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700371 except Exception:
372 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700373 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700374 else:
375 # namespace is not clear!
376 main.log.error( name + " component already exists!" )
Devin Lim44075962017-08-11 10:56:37 -0700377 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700378
379 def setBenchOptions( self, name ):
380 """
381 Parse the cluster options to create an ONOS "bench" component with the given name
382 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000383 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
384 main.componentDictionary[name]['type'] = "OnosDriver"
385 home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
386 main.componentDictionary[name]['home'] = self.checkOptions( home, None )
387 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hallca319892017-06-15 15:25:22 -0700388
389 def createBenchComponent( self, name ):
390 """
391 Creates a new onos "bench" component.
392
393 Arguments:
394 name - The string of the name of this component. The new component
395 will be assigned to main.<name> .
396 In addition, main.<name>.name = str( name )
397 """
398 try:
399 # look to see if this component already exists
400 getattr( main, name )
401 except AttributeError:
402 # namespace is clear, creating component
403 self.setBenchOptions( name )
404 return main.componentInit( name )
405 except pexpect.EOF:
406 main.log.error( self.name + ": EOF exception found" )
407 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700408 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700409 except Exception:
410 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700411 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700412 else:
413 # namespace is not clear!
414 main.log.error( name + " component already exists!" )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
Jon Hallca319892017-06-15 15:25:22 -0700416
Jon Hall4173b242017-09-12 17:04:38 -0700417 def setServerOptions( self, name, ipAddress ):
418 """
419 Parse the cluster options to create an ONOS "server" component with the given name
420
421 Arguments:
422 name - The name of the server componet
423 ipAddress - The ip address of the server
424 """
425 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
426 main.componentDictionary[name]['type'] = "OnosDriver"
427 main.componentDictionary[name]['host'] = ipAddress
428 home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
429 main.componentDictionary[name]['home'] = self.checkOptions( home, None )
You Wang4cc61912018-08-28 10:10:58 -0700430 # TODO: for now we use karaf user name and password also for logging to the onos nodes
Jon Hall06fd0df2021-01-25 15:50:06 -0800431 # FIXME: We shouldn't use karaf* for this, what we want is another set of variables to
432 # login to a shell on the server ONOS is running on
Siddesh52750622021-03-05 19:52:03 +0000433 main.componentDictionary[name]['user'] = self.nodeUser
434 main.componentDictionary[name]['password'] = self.nodePass
Jon Hall4173b242017-09-12 17:04:38 -0700435 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
Jon Hall4173b242017-09-12 17:04:38 -0700436
Jon Hall4173b242017-09-12 17:04:38 -0700437 def createServerComponent( self, name, ipAddress ):
438 """
439 Creates a new onos "server" component. This will be connected to the
440 node ONOS is running on.
441
442 Arguments:
443 name - The string of the name of this component. The new component
444 will be assigned to main.<name> .
445 In addition, main.<name>.name = str( name )
446 ipAddress - The ip address of the server
447 """
448 try:
449 # look to see if this component already exists
450 getattr( main, name )
451 except AttributeError:
452 # namespace is clear, creating component
453 self.setServerOptions( name, ipAddress )
454 return main.componentInit( name )
455 except pexpect.EOF:
456 main.log.error( self.name + ": EOF exception found" )
457 main.log.error( self.name + ": " + self.handle.before )
458 main.cleanAndExit()
459 except Exception:
460 main.log.exception( self.name + ": Uncaught exception!" )
461 main.cleanAndExit()
462 else:
463 # namespace is not clear!
464 main.log.error( name + " component already exists!" )
465 main.cleanAndExit()
466
Jon Hall4173b242017-09-12 17:04:38 -0700467 def createComponents( self, prefix='', createServer=True ):
Jon Hallca319892017-06-15 15:25:22 -0700468 """
469 Creates a CLI and REST component for each nodes in the cluster
470 """
471 # TODO: This needs work to support starting two seperate clusters in one test
472 cliPrefix = prefix + "cli"
473 restPrefix = prefix + "rest"
474 benchPrefix = prefix + "bench"
Jon Hall4173b242017-09-12 17:04:38 -0700475 serverPrefix = prefix + "server"
Jon Hall06fd0df2021-01-25 15:50:06 -0800476 k8sPrefix = prefix + "k8s"
Jon Hallca319892017-06-15 15:25:22 -0700477 for i in xrange( 1, self.maxNodes + 1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000478 cliName = cliPrefix + str( i )
Jon Hallca319892017-06-15 15:25:22 -0700479 restName = restPrefix + str( i )
480 benchName = benchPrefix + str( i )
Jon Hall4173b242017-09-12 17:04:38 -0700481 serverName = serverPrefix + str( i )
Jon Hall06fd0df2021-01-25 15:50:06 -0800482 if self.kubeConfig:
483 k8sName = k8sPrefix + str( i )
Jon Hallca319892017-06-15 15:25:22 -0700484
485 # Unfortunately this means we need to have a cell set beofre running TestON,
486 # Even if it is just the entire possible cluster size
487 ip = self.onosIps[ 'OC' + str( i ) ]
488
Devin Lim142b5342017-07-20 15:22:39 -0700489 cli = self.createCliComponent( cliName, ip )
Jon Hallca319892017-06-15 15:25:22 -0700490 rest = self.createRestComponent( restName, ip )
491 bench = self.createBenchComponent( benchName )
Jon Hall4173b242017-09-12 17:04:38 -0700492 server = self.createServerComponent( serverName, ip ) if createServer else None
Jon Hall06fd0df2021-01-25 15:50:06 -0800493 k8s = self.createServerComponent( k8sName, ip ) if self.kubeConfig else None
494 if self.kubeConfig:
495 k8s.kubeConfig = self.kubeConfig
496 k8s.podName = None
Jon Hall3c0114c2020-08-11 15:07:42 -0700497 self.nodes.append( Controller( prefix + str( i ), ip, cli, rest, bench, i - 1,
Jon Hall06fd0df2021-01-25 15:50:06 -0800498 self.user_name, server=server, k8s=k8s,
Jon Hall3c0114c2020-08-11 15:07:42 -0700499 dockerPrompt=self.dockerPrompt ) )