blob: dbb12477e3bf818cbb90e2e7693bf646f241b037 [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 Hall69b2b982016-05-11 12:04:59 -070021"Functions for using the SimpleHTTPServer python module"
22import re
23
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070024
Jon Hall69b2b982016-05-11 12:04:59 -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 ) )
62 handle.expect( "\$" )
63 # 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 Hall69b2b982016-05-11 12:04:59 -070069 cmd += " &"
70 handle.sendline( cmd )
71 handle.expect( "\$" )
72 response = handle.before
73 # Return to home dir
74 handle.sendline( "cd " + component.home )
75 handle.expect( "\$" )
76 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 )
80 retValue = main.FALSE
81 # capture PID for later use
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070082 # EX: [ 1 ] 67987
Jon Hall69b2b982016-05-11 12:04:59 -070083 match = re.search( "\[\d\] (?P<PID>\d+)", response )
84 if match:
85 self.PID = match.group( "PID" )
86 else:
87 main.log.warn( "Could not find PID" )
88 else:
89 main.log.error( "Component handle is not set" )
90 retValue = main.FALSE
91 except Exception:
92 main.log.exception( "Error starting web server" )
93 retValue = main.FALSE
94 return retValue
95
96 def stop( self ):
97 """
98 Kills the process of the server. Note that this function must be run
99 from the same instance of the server class that the server was started
100 on.
101 """
102 retValue = main.TRUE
103 try:
104 main.log.info( "Stopping Server." )
105 assert self.component, "Component not specified"
106 assert self.PID, "PID not found"
107 if self.component.handle:
108 handle = self.component.handle
109 cmd = "sudo kill {}".format( self.PID )
110 handle.sendline( cmd )
111 handle.expect( "\$" )
112 # TODO: What is bad output? cannot sudo?
113 else:
114 main.log.error( "Component handle is not set" )
115 retValue = main.FALSE
116 except Exception:
117 main.log.exception( "Error stopping web server" )
118 retValue = main.FALSE
119 return retValue
120
121 def generateFile( self, nodes, equal=False, filename="cluster.json" ):
122 """
123 Generate custom metadata file in the root directory using the custom
124 onos-gen-partitions file which should also be located in the root
125 directory.
126
127 Note that this function needs to be run after the start function has
128 been called for this instance.
129
130 Arguments:
131 - nodes = The number of ONOS nodes to include in the cluster. Will
132 include nodes in ascending order, I.E. OC1, OC2, etc
133
134 Optional Arguments:
135 - equal = Specifies whether all nodes should participate in every
136 partition. Defaults to False.
137 - filename = The name of the file to save the cluster metadata to.
138 Defaults to "cluster.json".
139 Returns:
140 main.TRUE if the command succedes or main.FALSE if there is an error.
141 """
142 retValue = main.TRUE
143 try:
144 if self.component.handle:
145 assert self.component, "Component not specified. Please start the server first"
146 assert self.rootDir, "Root directory not found"
147 handle = self.component.handle
148 # cd to rootDir
149 handle.sendline( "cd " + str( self.rootDir ) )
150 handle.expect( "\$" )
151 cmd = "./onos-gen-partitions {} {} ".format( filename, nodes )
152 if equal:
153 cmd += "-e"
154 handle.sendline( cmd )
155 handle.expect( "\$" )
156 response = handle.before
157 # Return to home dir
158 handle.sendline( "cd " + self.component.home )
159 handle.expect( "\$" )
160 response += handle.before
161 if "Traceback" in response:
162 main.log.error( handle.before )
163 retValue = main.FALSE
164 else:
165 main.log.error( "Component handle is not set" )
166 retValue = main.FALSE
167 except Exception:
168 main.log.exception( "Error generating metadata file" )
169 return retValue