Jon Hall | 69b2b98 | 2016-05-11 12:04:59 -0700 | [diff] [blame] | 1 | "Functions for using the SimpleHTTPServer python module" |
| 2 | import re |
| 3 | |
| 4 | class Server(): |
| 5 | |
| 6 | def __init__( self ): |
| 7 | self.default = '' |
| 8 | self.PID = -1 |
| 9 | self.component = None |
| 10 | self.rootDir = None |
| 11 | |
| 12 | def __del__( self ): |
| 13 | self.stop() |
| 14 | |
| 15 | def start( self, component, rootDir, port=8000, logDir=None ): |
| 16 | """ |
| 17 | Start SimpleHTTPServer as a background process from rootDir on the |
| 18 | given component. The webserver will listen on port and if specified, |
| 19 | output will be redirected to logDir. |
| 20 | |
| 21 | Arguments: |
| 22 | - component = The TestON component handle to start the webserver on |
| 23 | - rootDir = The root directory for the web content |
| 24 | - port = The port number for the webserver to listen on. Defaults to 8000 |
| 25 | - logDir = If specified, the output of the webserver will be redirected |
| 26 | to this file. Note that this should be either an absolute path |
| 27 | or relative to rootDir. |
| 28 | Returns: |
| 29 | main.TRUE if the command succedes or main.FALSE if there is an error. |
| 30 | """ |
| 31 | retValue = main.TRUE |
| 32 | self.rootDir = rootDir |
| 33 | try: |
| 34 | # Save component for this instance so other functions can use it |
| 35 | self.component = component |
| 36 | main.log.info( "Starting SimpleHTTPServer on " + component.name ) |
| 37 | if component.handle: |
| 38 | handle = component.handle |
| 39 | # cd to rootDir |
| 40 | handle.sendline( "cd " + str( rootDir ) ) |
| 41 | handle.expect( "\$" ) |
| 42 | # Start server |
| 43 | cmd = "python -m SimpleHTTPServer {}".format( port ) |
| 44 | if logDir: |
| 45 | cmd += " &> {}".format( logDir ) # pipe all output to a file |
| 46 | else: |
| 47 | cmd += "&> {dev/null}" # Throw away all output |
| 48 | cmd += " &" |
| 49 | handle.sendline( cmd ) |
| 50 | handle.expect( "\$" ) |
| 51 | response = handle.before |
| 52 | # Return to home dir |
| 53 | handle.sendline( "cd " + component.home ) |
| 54 | handle.expect( "\$" ) |
| 55 | response += handle.before |
| 56 | if "Exit" in response: |
| 57 | main.log.error( "Error starting server. Check server log for details" ) |
| 58 | main.log.debug( handle.before ) |
| 59 | retValue = main.FALSE |
| 60 | # capture PID for later use |
| 61 | # EX: [1] 67987 |
| 62 | match = re.search( "\[\d\] (?P<PID>\d+)", response ) |
| 63 | if match: |
| 64 | self.PID = match.group( "PID" ) |
| 65 | else: |
| 66 | main.log.warn( "Could not find PID" ) |
| 67 | else: |
| 68 | main.log.error( "Component handle is not set" ) |
| 69 | retValue = main.FALSE |
| 70 | except Exception: |
| 71 | main.log.exception( "Error starting web server" ) |
| 72 | retValue = main.FALSE |
| 73 | return retValue |
| 74 | |
| 75 | def stop( self ): |
| 76 | """ |
| 77 | Kills the process of the server. Note that this function must be run |
| 78 | from the same instance of the server class that the server was started |
| 79 | on. |
| 80 | """ |
| 81 | retValue = main.TRUE |
| 82 | try: |
| 83 | main.log.info( "Stopping Server." ) |
| 84 | assert self.component, "Component not specified" |
| 85 | assert self.PID, "PID not found" |
| 86 | if self.component.handle: |
| 87 | handle = self.component.handle |
| 88 | cmd = "sudo kill {}".format( self.PID ) |
| 89 | handle.sendline( cmd ) |
| 90 | handle.expect( "\$" ) |
| 91 | # TODO: What is bad output? cannot sudo? |
| 92 | else: |
| 93 | main.log.error( "Component handle is not set" ) |
| 94 | retValue = main.FALSE |
| 95 | except Exception: |
| 96 | main.log.exception( "Error stopping web server" ) |
| 97 | retValue = main.FALSE |
| 98 | return retValue |
| 99 | |
| 100 | def generateFile( self, nodes, equal=False, filename="cluster.json" ): |
| 101 | """ |
| 102 | Generate custom metadata file in the root directory using the custom |
| 103 | onos-gen-partitions file which should also be located in the root |
| 104 | directory. |
| 105 | |
| 106 | Note that this function needs to be run after the start function has |
| 107 | been called for this instance. |
| 108 | |
| 109 | Arguments: |
| 110 | - nodes = The number of ONOS nodes to include in the cluster. Will |
| 111 | include nodes in ascending order, I.E. OC1, OC2, etc |
| 112 | |
| 113 | Optional Arguments: |
| 114 | - equal = Specifies whether all nodes should participate in every |
| 115 | partition. Defaults to False. |
| 116 | - filename = The name of the file to save the cluster metadata to. |
| 117 | Defaults to "cluster.json". |
| 118 | Returns: |
| 119 | main.TRUE if the command succedes or main.FALSE if there is an error. |
| 120 | """ |
| 121 | retValue = main.TRUE |
| 122 | try: |
| 123 | if self.component.handle: |
| 124 | assert self.component, "Component not specified. Please start the server first" |
| 125 | assert self.rootDir, "Root directory not found" |
| 126 | handle = self.component.handle |
| 127 | # cd to rootDir |
| 128 | handle.sendline( "cd " + str( self.rootDir ) ) |
| 129 | handle.expect( "\$" ) |
| 130 | cmd = "./onos-gen-partitions {} {} ".format( filename, nodes ) |
| 131 | if equal: |
| 132 | cmd += "-e" |
| 133 | handle.sendline( cmd ) |
| 134 | handle.expect( "\$" ) |
| 135 | response = handle.before |
| 136 | # Return to home dir |
| 137 | handle.sendline( "cd " + self.component.home ) |
| 138 | handle.expect( "\$" ) |
| 139 | response += handle.before |
| 140 | if "Traceback" in response: |
| 141 | main.log.error( handle.before ) |
| 142 | retValue = main.FALSE |
| 143 | else: |
| 144 | main.log.error( "Component handle is not set" ) |
| 145 | retValue = main.FALSE |
| 146 | except Exception: |
| 147 | main.log.exception( "Error generating metadata file" ) |
| 148 | return retValue |