4 # Copyright (C) 2007, 2008 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 from cStringIO import StringIO
34 from ganeti import constants
35 from ganeti import serializer
36 from ganeti import utils
39 HTTP_GANETI_VERSION = "Ganeti %s" % constants.RELEASE_VERSION
43 HTTP_NOT_MODIFIED = 304
53 HTTP_DELETE = "DELETE"
57 HTTP_SERVER = "Server"
59 HTTP_USER_AGENT = "User-Agent"
60 HTTP_CONTENT_TYPE = "Content-Type"
61 HTTP_CONTENT_LENGTH = "Content-Length"
62 HTTP_CONNECTION = "Connection"
63 HTTP_KEEP_ALIVE = "Keep-Alive"
64 HTTP_WWW_AUTHENTICATE = "WWW-Authenticate"
65 HTTP_AUTHORIZATION = "Authorization"
66 HTTP_AUTHENTICATION_INFO = "Authentication-Info"
69 _SSL_UNEXPECTED_EOF = "Unexpected EOF"
75 SOCKOP_HANDSHAKE) = range(4)
77 # send/receive quantum
81 class HttpError(Exception):
82 """Internal exception for HTTP errors.
84 This should only be used for internal error reporting.
89 class HttpConnectionClosed(Exception):
90 """Internal exception for a closed connection.
92 This should only be used for internal error reporting. Only use
93 it if there's no other way to report this condition.
98 class HttpSessionHandshakeUnexpectedEOF(HttpError):
99 """Internal exception for errors during SSL handshake.
101 This should only be used for internal error reporting.
106 class HttpSocketTimeout(Exception):
107 """Internal exception for socket timeouts.
109 This should only be used for internal error reporting.
114 class HttpException(Exception):
118 def __init__(self, message=None, headers=None):
119 Exception.__init__(self)
120 self.message = message
121 self.headers = headers
124 class HttpBadRequest(HttpException):
127 RFC2616, 10.4.1: The request could not be understood by the server
128 due to malformed syntax. The client SHOULD NOT repeat the request
129 without modifications.
135 class HttpUnauthorized(HttpException):
138 RFC2616, section 10.4.2: The request requires user
139 authentication. The response MUST include a WWW-Authenticate header
140 field (section 14.47) containing a challenge applicable to the
147 class HttpForbidden(HttpException):
150 RFC2616, 10.4.4: The server understood the request, but is refusing
151 to fulfill it. Authorization will not help and the request SHOULD
158 class HttpNotFound(HttpException):
161 RFC2616, 10.4.5: The server has not found anything matching the
162 Request-URI. No indication is given of whether the condition is
163 temporary or permanent.
169 class HttpMethodNotAllowed(HttpException):
170 """405 Method Not Allowed
172 RFC2616, 10.4.6: The method specified in the Request-Line is not
173 allowed for the resource identified by the Request-URI. The response
174 MUST include an Allow header containing a list of valid methods for
175 the requested resource.
181 class HttpRequestTimeout(HttpException):
182 """408 Request Timeout
184 RFC2616, 10.4.9: The client did not produce a request within the
185 time that the server was prepared to wait. The client MAY repeat the
186 request without modifications at any later time.
192 class HttpConflict(HttpException):
195 RFC2616, 10.4.10: The request could not be completed due to a
196 conflict with the current state of the resource. This code is only
197 allowed in situations where it is expected that the user might be
198 able to resolve the conflict and resubmit the request.
204 class HttpGone(HttpException):
207 RFC2616, 10.4.11: The requested resource is no longer available at
208 the server and no forwarding address is known. This condition is
209 expected to be considered permanent.
215 class HttpLengthRequired(HttpException):
216 """411 Length Required
218 RFC2616, 10.4.12: The server refuses to accept the request without a
219 defined Content-Length. The client MAY repeat the request if it adds
220 a valid Content-Length header field containing the length of the
221 message-body in the request message.
227 class HttpPreconditionFailed(HttpException):
228 """412 Precondition Failed
230 RFC2616, 10.4.13: The precondition given in one or more of the
231 request-header fields evaluated to false when it was tested on the
238 class HttpInternalServerError(HttpException):
239 """500 Internal Server Error
241 RFC2616, 10.5.1: The server encountered an unexpected condition
242 which prevented it from fulfilling the request.
248 class HttpNotImplemented(HttpException):
249 """501 Not Implemented
251 RFC2616, 10.5.2: The server does not support the functionality
252 required to fulfill the request.
258 class HttpBadGateway(HttpException):
261 RFC2616, 10.5.3: The server, while acting as a gateway or proxy,
262 received an invalid response from the upstream server it accessed in
263 attempting to fulfill the request.
269 class HttpServiceUnavailable(HttpException):
270 """503 Service Unavailable
272 RFC2616, 10.5.4: The server is currently unable to handle the
273 request due to a temporary overloading or maintenance of the server.
279 class HttpGatewayTimeout(HttpException):
280 """504 Gateway Timeout
282 RFC2616, 10.5.5: The server, while acting as a gateway or proxy, did
283 not receive a timely response from the upstream server specified by
284 the URI (e.g. HTTP, FTP, LDAP) or some other auxiliary server
285 (e.g. DNS) it needed to access in attempting to complete the
292 class HttpVersionNotSupported(HttpException):
293 """505 HTTP Version Not Supported
295 RFC2616, 10.5.6: The server does not support, or refuses to support,
296 the HTTP protocol version that was used in the request message.
302 class HttpJsonConverter: # pylint: disable-msg=W0232
303 CONTENT_TYPE = "application/json"
307 return serializer.DumpJson(data)
311 return serializer.LoadJson(data)
314 def WaitForSocketCondition(sock, event, timeout):
315 """Waits for a condition to occur on the socket.
318 @param sock: Wait for events on this socket
320 @param event: ORed condition (see select module)
321 @type timeout: float or None
322 @param timeout: Timeout in seconds
324 @return: None for timeout, otherwise occured conditions
327 check = (event | select.POLLPRI |
328 select.POLLNVAL | select.POLLHUP | select.POLLERR)
330 if timeout is not None:
331 # Poller object expects milliseconds
334 poller = select.poll()
335 poller.register(sock, event)
338 # TODO: If the main thread receives a signal and we have no timeout, we
339 # could wait forever. This should check a global "quit" flag or
340 # something every so often.
341 io_events = poller.poll(timeout)
345 for (_, evcond) in io_events:
349 poller.unregister(sock)
352 def SocketOperation(sock, op, arg1, timeout):
353 """Wrapper around socket functions.
355 This function abstracts error handling for socket operations, especially
356 for the complicated interaction with OpenSSL.
359 @param sock: Socket for the operation
361 @param op: Operation to execute (SOCKOP_* constants)
363 @param arg1: Parameter for function (if needed)
364 @type timeout: None or float
365 @param timeout: Timeout in seconds or None
366 @return: Return value of socket function
369 # TODO: event_poll/event_check/override
370 if op in (SOCKOP_SEND, SOCKOP_HANDSHAKE):
371 event_poll = select.POLLOUT
373 elif op == SOCKOP_RECV:
374 event_poll = select.POLLIN
376 elif op == SOCKOP_SHUTDOWN:
379 # The timeout is only used when OpenSSL requests polling for a condition.
380 # It is not advisable to have no timeout for shutdown.
384 raise AssertionError("Invalid socket operation")
386 # Handshake is only supported by SSL sockets
387 if (op == SOCKOP_HANDSHAKE and
388 not isinstance(sock, OpenSSL.SSL.ConnectionType)):
391 # No override by default
395 # Poll only for certain operations and when asked for by an override
396 if event_override or op in (SOCKOP_SEND, SOCKOP_RECV, SOCKOP_HANDSHAKE):
398 wait_for_event = event_override
400 wait_for_event = event_poll
402 event = WaitForSocketCondition(sock, wait_for_event, timeout)
404 raise HttpSocketTimeout()
406 if event & (select.POLLNVAL | select.POLLHUP | select.POLLERR):
407 # Let the socket functions handle these
410 if not event & wait_for_event:
418 if op == SOCKOP_SEND:
419 return sock.send(arg1)
421 elif op == SOCKOP_RECV:
422 return sock.recv(arg1)
424 elif op == SOCKOP_SHUTDOWN:
425 if isinstance(sock, OpenSSL.SSL.ConnectionType):
426 # PyOpenSSL's shutdown() doesn't take arguments
427 return sock.shutdown()
429 return sock.shutdown(arg1)
431 elif op == SOCKOP_HANDSHAKE:
432 return sock.do_handshake()
434 except OpenSSL.SSL.WantWriteError:
435 # OpenSSL wants to write, poll for POLLOUT
436 event_override = select.POLLOUT
439 except OpenSSL.SSL.WantReadError:
440 # OpenSSL wants to read, poll for POLLIN
441 event_override = select.POLLIN | select.POLLPRI
444 except OpenSSL.SSL.WantX509LookupError:
447 except OpenSSL.SSL.ZeroReturnError, err:
448 # SSL Connection has been closed. In SSL 3.0 and TLS 1.0, this only
449 # occurs if a closure alert has occurred in the protocol, i.e. the
450 # connection has been closed cleanly. Note that this does not
451 # necessarily mean that the transport layer (e.g. a socket) has been
453 if op == SOCKOP_SEND:
454 # Can happen during a renegotiation
455 raise HttpConnectionClosed(err.args)
456 elif op == SOCKOP_RECV:
459 # SSL_shutdown shouldn't return SSL_ERROR_ZERO_RETURN
460 raise socket.error(err.args)
462 except OpenSSL.SSL.SysCallError, err:
463 if op == SOCKOP_SEND:
464 # arg1 is the data when writing
465 if err.args and err.args[0] == -1 and arg1 == "":
466 # errors when writing empty strings are expected
470 if err.args == (-1, _SSL_UNEXPECTED_EOF):
471 if op == SOCKOP_RECV:
473 elif op == SOCKOP_HANDSHAKE:
474 # Can happen if peer disconnects directly after the connection is
476 raise HttpSessionHandshakeUnexpectedEOF(err.args)
478 raise socket.error(err.args)
480 except OpenSSL.SSL.Error, err:
481 raise socket.error(err.args)
483 except socket.error, err:
484 if err.args and err.args[0] == errno.EAGAIN:
491 def ShutdownConnection(sock, close_timeout, write_timeout, msgreader, force):
492 """Closes the connection.
495 @param sock: Socket to be shut down
496 @type close_timeout: float
497 @param close_timeout: How long to wait for the peer to close
499 @type write_timeout: float
500 @param write_timeout: Write timeout for shutdown
501 @type msgreader: http.HttpMessageReader
502 @param msgreader: Request message reader, used to determine whether
503 peer should close connection
505 @param force: Whether to forcibly close the connection without
509 #print msgreader.peer_will_close, force
510 if msgreader and msgreader.peer_will_close and not force:
511 # Wait for peer to close
513 # Check whether it's actually closed
514 if not SocketOperation(sock, SOCKOP_RECV, 1, close_timeout):
516 except (socket.error, HttpError, HttpSocketTimeout):
517 # Ignore errors at this stage
520 # Close the connection from our side
522 # We don't care about the return value, see NOTES in SSL_shutdown(3).
523 SocketOperation(sock, SOCKOP_SHUTDOWN, socket.SHUT_RDWR,
525 except HttpSocketTimeout:
526 raise HttpError("Timeout while shutting down connection")
527 except socket.error, err:
529 if not (err.args and err.args[0] == errno.ENOTCONN):
530 raise HttpError("Error while shutting down connection: %s" % err)
533 def Handshake(sock, write_timeout):
534 """Shakes peer's hands.
537 @param sock: Socket to be shut down
538 @type write_timeout: float
539 @param write_timeout: Write timeout for handshake
543 return SocketOperation(sock, SOCKOP_HANDSHAKE, None, write_timeout)
544 except HttpSocketTimeout:
545 raise HttpError("Timeout during SSL handshake")
546 except socket.error, err:
547 raise HttpError("Error in SSL handshake: %s" % err)
551 """Initializes the SSL infrastructure.
553 This function is idempotent.
556 if not OpenSSL.rand.status():
557 raise EnvironmentError("OpenSSL could not collect enough entropy"
560 # TODO: Maybe add some additional seeding for OpenSSL's PRNG
563 class HttpSslParams(object):
564 """Data class for SSL key and certificate.
567 def __init__(self, ssl_key_path, ssl_cert_path):
568 """Initializes this class.
570 @type ssl_key_path: string
571 @param ssl_key_path: Path to file containing SSL key in PEM format
572 @type ssl_cert_path: string
573 @param ssl_cert_path: Path to file containing SSL certificate
577 self.ssl_key_pem = utils.ReadFile(ssl_key_path)
578 self.ssl_cert_pem = utils.ReadFile(ssl_cert_path)
581 return OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,
584 def GetCertificate(self):
585 return OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
589 class HttpBase(object):
590 """Base class for HTTP server and client.
594 self.using_ssl = None
595 self._ssl_params = None
597 self._ssl_cert = None
599 def _CreateSocket(self, ssl_params, ssl_verify_peer):
600 """Creates a TCP socket and initializes SSL if needed.
602 @type ssl_params: HttpSslParams
603 @param ssl_params: SSL key and certificate
604 @type ssl_verify_peer: bool
605 @param ssl_verify_peer: Whether to require client certificate
606 and compare it with our certificate
609 self._ssl_params = ssl_params
611 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
613 # Should we enable SSL?
614 self.using_ssl = ssl_params is not None
616 if not self.using_ssl:
619 self._ssl_key = ssl_params.GetKey()
620 self._ssl_cert = ssl_params.GetCertificate()
622 ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
623 ctx.set_options(OpenSSL.SSL.OP_NO_SSLv2)
625 ctx.use_privatekey(self._ssl_key)
626 ctx.use_certificate(self._ssl_cert)
627 ctx.check_privatekey()
630 ctx.set_verify(OpenSSL.SSL.VERIFY_PEER |
631 OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
632 self._SSLVerifyCallback)
634 return OpenSSL.SSL.Connection(ctx, sock)
636 def _SSLVerifyCallback(self, conn, cert, errnum, errdepth, ok):
637 """Verify the certificate provided by the peer
639 We only compare fingerprints. The client must use the same certificate as
643 # some parameters are unused, but this is the API
644 # pylint: disable-msg=W0613
645 assert self._ssl_params, "SSL not initialized"
647 return (self._ssl_cert.digest("sha1") == cert.digest("sha1") and
648 self._ssl_cert.digest("md5") == cert.digest("md5"))
651 class HttpMessage(object):
652 """Data structure for HTTP message.
656 self.start_line = None
659 self.decoded_body = None
662 class HttpClientToServerStartLine(object):
663 """Data structure for HTTP request start line.
666 def __init__(self, method, path, version):
669 self.version = version
672 return "%s %s %s" % (self.method, self.path, self.version)
675 class HttpServerToClientStartLine(object):
676 """Data structure for HTTP response start line.
679 def __init__(self, version, code, reason):
680 self.version = version
685 return "%s %s %s" % (self.version, self.code, self.reason)
688 class HttpMessageWriter(object):
689 """Writes an HTTP message to a socket.
692 def __init__(self, sock, msg, write_timeout):
693 """Initializes this class and writes an HTTP message to a socket.
696 @param sock: Socket to be written to
697 @type msg: http.HttpMessage
698 @param msg: HTTP message to be written
699 @type write_timeout: float
700 @param write_timeout: Write timeout for socket
705 self._PrepareMessage()
707 buf = self._FormatMessage()
712 # Send only SOCK_BUF_SIZE bytes at a time
713 data = buf[pos:(pos + SOCK_BUF_SIZE)]
715 sent = SocketOperation(sock, SOCKOP_SEND, data, write_timeout)
720 assert pos == end, "Message wasn't sent completely"
722 def _PrepareMessage(self):
723 """Prepares the HTTP message by setting mandatory headers.
726 # RFC2616, section 4.3: "The presence of a message-body in a request is
727 # signaled by the inclusion of a Content-Length or Transfer-Encoding header
728 # field in the request's message-headers."
730 self._msg.headers[HTTP_CONTENT_LENGTH] = len(self._msg.body)
732 def _FormatMessage(self):
733 """Serializes the HTTP message into a string.
739 buf.write(str(self._msg.start_line))
743 if self._msg.start_line.version != HTTP_0_9:
744 for name, value in self._msg.headers.iteritems():
745 buf.write("%s: %s\r\n" % (name, value))
749 # Add message body if needed
750 if self.HasMessageBody():
751 buf.write(self._msg.body)
754 logging.warning("Ignoring message body")
756 return buf.getvalue()
758 def HasMessageBody(self):
759 """Checks whether the HTTP message contains a body.
761 Can be overridden by subclasses.
764 return bool(self._msg.body)
767 class HttpMessageReader(object):
768 """Reads HTTP message from socket.
772 START_LINE_LENGTH_MAX = None
773 HEADER_LENGTH_MAX = None
775 # Parser state machine
776 PS_START_LINE = "start-line"
777 PS_HEADERS = "headers"
778 PS_BODY = "entity-body"
779 PS_COMPLETE = "complete"
781 def __init__(self, sock, msg, read_timeout):
782 """Reads an HTTP message from a socket.
785 @param sock: Socket to be read from
786 @type msg: http.HttpMessage
787 @param msg: Object for the read message
788 @type read_timeout: float
789 @param read_timeout: Read timeout for socket
795 self.start_line_buffer = None
796 self.header_buffer = StringIO()
797 self.body_buffer = StringIO()
798 self.parser_status = self.PS_START_LINE
799 self.content_length = None
800 self.peer_will_close = None
804 while self.parser_status != self.PS_COMPLETE:
805 # TODO: Don't read more than necessary (Content-Length), otherwise
806 # data might be lost and/or an error could occur
807 data = SocketOperation(sock, SOCKOP_RECV, SOCK_BUF_SIZE, read_timeout)
814 # Do some parsing and error checking while more data arrives
815 buf = self._ContinueParsing(buf, eof)
817 # Must be done only after the buffer has been evaluated
818 # TODO: Connection-length < len(data read) and connection closed
820 self.parser_status in (self.PS_START_LINE,
822 raise HttpError("Connection closed prematurely")
825 buf = self._ContinueParsing(buf, True)
827 assert self.parser_status == self.PS_COMPLETE
828 assert not buf, "Parser didn't read full response"
830 msg.body = self.body_buffer.getvalue()
832 # TODO: Content-type, error handling
834 msg.decoded_body = HttpJsonConverter().Decode(msg.body)
836 msg.decoded_body = None
839 logging.debug("Message body: %s", msg.decoded_body)
841 def _ContinueParsing(self, buf, eof):
842 """Main function for HTTP message state machine.
845 @param buf: Receive buffer
847 @param eof: Whether we've reached EOF on the socket
849 @return: Updated receive buffer
852 # TODO: Use offset instead of slicing when possible
853 if self.parser_status == self.PS_START_LINE:
856 idx = buf.find("\r\n")
858 # RFC2616, section 4.1: "In the interest of robustness, servers SHOULD
859 # ignore any empty line(s) received where a Request-Line is expected.
860 # In other words, if the server is reading the protocol stream at the
861 # beginning of a message and receives a CRLF first, it should ignore
864 # TODO: Limit number of CRLFs/empty lines for safety?
869 self.start_line_buffer = buf[:idx]
871 self._CheckStartLineLength(len(self.start_line_buffer))
873 # Remove status line, including CRLF
876 self.msg.start_line = self.ParseStartLine(self.start_line_buffer)
878 self.parser_status = self.PS_HEADERS
880 # Check whether incoming data is getting too large, otherwise we just
881 # fill our read buffer.
882 self._CheckStartLineLength(len(buf))
886 # TODO: Handle messages without headers
887 if self.parser_status == self.PS_HEADERS:
888 # Wait for header end
889 idx = buf.find("\r\n\r\n")
891 self.header_buffer.write(buf[:idx + 2])
893 self._CheckHeaderLength(self.header_buffer.tell())
895 # Remove headers, including CRLF
900 self.parser_status = self.PS_BODY
902 # Check whether incoming data is getting too large, otherwise we just
903 # fill our read buffer.
904 self._CheckHeaderLength(len(buf))
906 if self.parser_status == self.PS_BODY:
907 # TODO: Implement max size for body_buffer
908 self.body_buffer.write(buf)
911 # Check whether we've read everything
913 # RFC2616, section 4.4: "When a message-body is included with a message,
914 # the transfer-length of that body is determined by one of the following
915 # [...] 5. By the server closing the connection. (Closing the connection
916 # cannot be used to indicate the end of a request body, since that would
917 # leave no possibility for the server to send back a response.)"
919 # TODO: Error when buffer length > Content-Length header
921 self.content_length is None or
922 (self.content_length is not None and
923 self.body_buffer.tell() >= self.content_length)):
924 self.parser_status = self.PS_COMPLETE
928 def _CheckStartLineLength(self, length):
929 """Limits the start line buffer size.
932 @param length: Buffer size
935 if (self.START_LINE_LENGTH_MAX is not None and
936 length > self.START_LINE_LENGTH_MAX):
937 raise HttpError("Start line longer than %d chars" %
938 self.START_LINE_LENGTH_MAX)
940 def _CheckHeaderLength(self, length):
941 """Limits the header buffer size.
944 @param length: Buffer size
947 if (self.HEADER_LENGTH_MAX is not None and
948 length > self.HEADER_LENGTH_MAX):
949 raise HttpError("Headers longer than %d chars" % self.HEADER_LENGTH_MAX)
951 def ParseStartLine(self, start_line):
952 """Parses the start line of a message.
954 Must be overridden by subclass.
956 @type start_line: string
957 @param start_line: Start line string
960 raise NotImplementedError()
962 def _WillPeerCloseConnection(self):
963 """Evaluate whether peer will close the connection.
966 @return: Whether peer will close the connection
969 # RFC2616, section 14.10: "HTTP/1.1 defines the "close" connection option
970 # for the sender to signal that the connection will be closed after
971 # completion of the response. For example,
975 # in either the request or the response header fields indicates that the
976 # connection SHOULD NOT be considered `persistent' (section 8.1) after the
977 # current request/response is complete."
979 hdr_connection = self.msg.headers.get(HTTP_CONNECTION, None)
981 hdr_connection = hdr_connection.lower()
983 # An HTTP/1.1 server is assumed to stay open unless explicitly closed.
984 if self.msg.start_line.version == HTTP_1_1:
985 return (hdr_connection and "close" in hdr_connection)
987 # Some HTTP/1.0 implementations have support for persistent connections,
988 # using rules different than HTTP/1.1.
990 # For older HTTP, Keep-Alive indicates persistent connection.
991 if self.msg.headers.get(HTTP_KEEP_ALIVE):
994 # At least Akamai returns a "Connection: Keep-Alive" header, which was
995 # supposed to be sent by the client.
996 if hdr_connection and "keep-alive" in hdr_connection:
1001 def _ParseHeaders(self):
1002 """Parses the headers.
1004 This function also adjusts internal variables based on header values.
1006 RFC2616, section 4.3: The presence of a message-body in a request is
1007 signaled by the inclusion of a Content-Length or Transfer-Encoding header
1008 field in the request's message-headers.
1012 self.header_buffer.seek(0, 0)
1013 self.msg.headers = mimetools.Message(self.header_buffer, 0)
1015 self.peer_will_close = self._WillPeerCloseConnection()
1017 # Do we have a Content-Length header?
1018 hdr_content_length = self.msg.headers.get(HTTP_CONTENT_LENGTH, None)
1019 if hdr_content_length:
1021 self.content_length = int(hdr_content_length)
1022 except (TypeError, ValueError):
1023 self.content_length = None
1024 if self.content_length is not None and self.content_length < 0:
1025 self.content_length = None
1027 # if the connection remains open and a content-length was not provided,
1028 # then assume that the connection WILL close.
1029 if self.content_length is None:
1030 self.peer_will_close = True