blob: 0c5e743a54d5d43eaeeb66acccd7f4ac7ddd29fc [file] [log] [blame]
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07001"""
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07002Copyright 2016 Open Networking Foundation ( ONF )
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07003
4Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
5the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
6or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070011 ( at your option ) any later version.
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070012
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20"""
Jon Hall9ebd1bd2016-04-19 01:37:17 -070021"Functions for using the SimpleHTTPServer python module"
22import re
23
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070024
Jon Hall9ebd1bd2016-04-19 01:37:17 -070025class Server():
26
27 def __init__( self ):
28 self.default = ''
29 self.PID = -1
30 self.component = None
31 self.rootDir = None
32
33 def __del__( self ):
34 self.stop()
35
36 def start( self, component, rootDir, port=8000, logDir=None ):
37 """
38 Start SimpleHTTPServer as a background process from rootDir on the
39 given component. The webserver will listen on port and if specified,
40 output will be redirected to logDir.
41
42 Arguments:
43 - component = The TestON component handle to start the webserver on
44 - rootDir = The root directory for the web content
45 - port = The port number for the webserver to listen on. Defaults to 8000
46 - logDir = If specified, the output of the webserver will be redirected
47 to this file. Note that this should be either an absolute path
48 or relative to rootDir.
49 Returns:
50 main.TRUE if the command succedes or main.FALSE if there is an error.
51 """
52 retValue = main.TRUE
53 self.rootDir = rootDir
54 try:
55 # Save component for this instance so other functions can use it
56 self.component = component
57 main.log.info( "Starting SimpleHTTPServer on " + component.name )
58 if component.handle:
59 handle = component.handle
60 # cd to rootDir
61 handle.sendline( "cd " + str( rootDir ) )
Jon Hallcd2604f2018-04-12 12:39:48 -070062 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070063 # Start server
64 cmd = "python -m SimpleHTTPServer {}".format( port )
65 if logDir:
66 cmd += " &> {}".format( logDir ) # pipe all output to a file
67 else:
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070068 cmd += "&> {dev/null}" # Throw away all output
Jon Hall9ebd1bd2016-04-19 01:37:17 -070069 cmd += " &"
70 handle.sendline( cmd )
Jon Hallcd2604f2018-04-12 12:39:48 -070071 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070072 response = handle.before
73 # Return to home dir
74 handle.sendline( "cd " + component.home )
Jon Hallcd2604f2018-04-12 12:39:48 -070075 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070076 response += handle.before
77 if "Exit" in response:
78 main.log.error( "Error starting server. Check server log for details" )
79 main.log.debug( handle.before )
Jon Hallcd2604f2018-04-12 12:39:48 -070080 # Show the log
81 handle.sendline( "cat {}".format( logDir ))
82 handle.expect( component.prompt )
83 main.log.debug( handle.before )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070084 retValue = main.FALSE
85 # capture PID for later use
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070086 # EX: [ 1 ] 67987
Jon Hall9ebd1bd2016-04-19 01:37:17 -070087 match = re.search( "\[\d\] (?P<PID>\d+)", response )
88 if match:
89 self.PID = match.group( "PID" )
90 else:
91 main.log.warn( "Could not find PID" )
92 else:
93 main.log.error( "Component handle is not set" )
94 retValue = main.FALSE
95 except Exception:
96 main.log.exception( "Error starting web server" )
97 retValue = main.FALSE
98 return retValue
99
100 def stop( self ):
101 """
102 Kills the process of the server. Note that this function must be run
103 from the same instance of the server class that the server was started
104 on.
105 """
106 retValue = main.TRUE
107 try:
108 main.log.info( "Stopping Server." )
109 assert self.component, "Component not specified"
110 assert self.PID, "PID not found"
111 if self.component.handle:
112 handle = self.component.handle
113 cmd = "sudo kill {}".format( self.PID )
114 handle.sendline( cmd )
Jon Hallcd2604f2018-04-12 12:39:48 -0700115 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700116 # TODO: What is bad output? cannot sudo?
117 else:
118 main.log.error( "Component handle is not set" )
119 retValue = main.FALSE
120 except Exception:
121 main.log.exception( "Error stopping web server" )
122 retValue = main.FALSE
123 return retValue
124
125 def generateFile( self, nodes, equal=False, filename="cluster.json" ):
126 """
127 Generate custom metadata file in the root directory using the custom
128 onos-gen-partitions file which should also be located in the root
129 directory.
130
131 Note that this function needs to be run after the start function has
132 been called for this instance.
133
134 Arguments:
135 - nodes = The number of ONOS nodes to include in the cluster. Will
136 include nodes in ascending order, I.E. OC1, OC2, etc
137
138 Optional Arguments:
139 - equal = Specifies whether all nodes should participate in every
140 partition. Defaults to False.
141 - filename = The name of the file to save the cluster metadata to.
142 Defaults to "cluster.json".
143 Returns:
144 main.TRUE if the command succedes or main.FALSE if there is an error.
145 """
146 retValue = main.TRUE
147 try:
148 if self.component.handle:
149 assert self.component, "Component not specified. Please start the server first"
150 assert self.rootDir, "Root directory not found"
151 handle = self.component.handle
152 # cd to rootDir
153 handle.sendline( "cd " + str( self.rootDir ) )
Jon Hallcd2604f2018-04-12 12:39:48 -0700154 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700155 cmd = "./onos-gen-partitions {} {} ".format( filename, nodes )
156 if equal:
157 cmd += "-e"
158 handle.sendline( cmd )
Jon Hallcd2604f2018-04-12 12:39:48 -0700159 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700160 response = handle.before
161 # Return to home dir
162 handle.sendline( "cd " + self.component.home )
Jon Hallcd2604f2018-04-12 12:39:48 -0700163 handle.expect( component.prompt )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700164 response += handle.before
165 if "Traceback" in response:
166 main.log.error( handle.before )
167 retValue = main.FALSE
168 else:
169 main.log.error( "Component handle is not set" )
170 retValue = main.FALSE
171 except Exception:
172 main.log.exception( "Error generating metadata file" )
173 return retValue