<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def open_connection(ip, username, password, function, args, write=False, conn_timeout=5, sess_timeout=300, port=22):
 """ Open a Jaide session with the device. To open a Jaide session to the device, and run the appropriate function against the device. Arguments for the downstream function are passed through. @param ip: String of the IP or hostname of the device to connect to. @type ip: str @param username: The string username used to connect to the device. @type useranme: str @param password: The string password used to connect to the device. @type password: str @param function: The downstream jaide.wrap function we'll be handing | off the jaide.Jaide() object to execute the command | once we've established the connection. @type function: function pointer. @param args: The arguments that we will hand off to the downstream | function. @type args: list @param write: If set, it would be a tuple that we pass back as part of | our return statement, so that any callback function | can know how and where to put the output from the device. @type write: False or tuple. @param conn_timeout: Sets the connection timeout value. This is how | we'll wait when connecting before classifying | the device unreachable. @type conn_timeout: int @param sess_timeout: Sets the session timeout value. A higher value may | be desired for long running commands, such as | 'request system snapshot slice alternate' @type sess_timeout: int @param port: The port to connect to the device on. Defaults to 22. @type port: int @returns: We could return either just a string of the output from the | device, or a tuple containing the information needed to write | to a file and the string output from the device. @rtype: Tuple or str """

    # start with the header line on the output.
    output = color('=' * 50 + '\nResults from device: %s\n' % ip, 'yel')
    try:
        # create the Jaide session object for the device.
        conn = Jaide(ip, username, password, connect_timeout=conn_timeout,
                     session_timeout=sess_timeout, port=port)
        if write is not False:
            return write, output + function(conn, *args)
        else:
            return output + function(conn, *args)
    except errors.SSHError:
        output += color('Unable to connect to port %s on device: %s\n' %
                        (str(port), ip), 'red')
    except errors.AuthenticationError:  # NCClient auth failure
        output += color('Authentication failed for device: %s' % ip, 'red')
    except AuthenticationException:  # Paramiko auth failure
        output += color('Authentication failed for device: %s' % ip, 'red')
    except SSHException as e:
        output += color('Error connecting to device: %s\nError: %s' %
                        (ip, str(e)), 'red')
    except socket.timeout:
        output += color('Timeout exceeded connecting to device: %s' % ip, 'red')
    except socket.gaierror:
        output += color('No route to host, or invalid hostname: %s' % ip, 'red')
    except socket.error:
        output += color('The device refused the connection on port %s, or '
                        'no route to host.' % port, 'red')
    if write is not False:
        return write, output
    else:
        return output