def _createXMLRPCServer(self): """ Create xml-rpc server over http or https. """ HTTP_HEADER_FLOWID = "FlowID" threadLocal = self.cif.threadLocal class LoggingMixIn: def log_request(self, code='-', size='-'): """Track from where client connections are coming.""" self.server.lastClient = self.client_address[0] self.server.lastClientTime = time.time() self.server.lastServerIP = self.request.getsockname()[0] # FIXME: The editNetwork API uses this log file to # determine if this host is still accessible. We use a # file (rather than an event) because editNetwork is # performed by a separate, root process. To clean this # up we need to move this to an API wrapper that is only # run for real clients (not vdsm internal API calls). file(constants.P_VDSM_CLIENT_LOG, 'w') server_address = (self.serverIP, int(self.serverPort)) if self.enableSSL: basehandler = SecureXMLRPCServer.SecureXMLRPCRequestHandler else: basehandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler class LoggingHandler(LoggingMixIn, basehandler): def setup(self): threadLocal.client = self.client_address[0] return basehandler.setup(self) def parse_request(self): r = (SecureXMLRPCServer.SecureXMLRPCRequestHandler. parse_request(self)) threadLocal.flowID = self.headers.get(HTTP_HEADER_FLOWID) return r if self.enableSSL: KEYFILE, CERTFILE, CACERT = self._getKeyCertFilenames() server = SecureXMLRPCServer.SecureThreadedXMLRPCServer( server_address, keyfile=KEYFILE, certfile=CERTFILE, ca_certs=CACERT, timeout=self.serverRespTimeout, requestHandler=LoggingHandler) else: server = utils.SimpleThreadedXMLRPCServer( server_address, requestHandler=LoggingHandler, logRequests=True) utils.closeOnExec(server.socket.fileno()) server.lastClientTime = 0 server.lastClient = '0.0.0.0' server.lastServerIP = '0.0.0.0' return server
def _create_socket(self, host, port): addr = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM) if not addr: raise Exception("Could not translate address '%s:%s'" % (self._host, str(self._port))) server_socket = socket.socket(addr[0][0], addr[0][1], addr[0][2]) utils.closeOnExec(server_socket.fileno()) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(addr[0][4]) server_socket.listen(5) server_socket.setblocking(0) return server_socket
def __init__(self, host, port, sslctx=None): self._sslctx = sslctx self._host = host self._port = port self._read_fd, self._write_fd = os.pipe() self._set_non_blocking(self._read_fd) utils.closeOnExec(self._read_fd) self._set_non_blocking(self._write_fd) utils.closeOnExec(self._write_fd) self._socket = self._create_socket(host, port) self._poller = select.poll() self._poller.register(self._socket, self.READ_ONLY_MASK) self._poller.register(self._read_fd, self.READ_ONLY_MASK) self._pending_connections = {} self._handlers = [] self._next_cleanup = 0 self._required_size = None
def __init__(self, host, port, sslctx=None): self._sslctx = sslctx self._host = host self._port = port self._read_fd, self._write_fd = os.pipe() utils.set_non_blocking(self._read_fd) utils.closeOnExec(self._read_fd) utils.set_non_blocking(self._write_fd) utils.closeOnExec(self._write_fd) self._socket = self._create_socket(host, port) self._poller = select.poll() self._poller.register(self._socket, self.READ_ONLY_MASK) self._poller.register(self._read_fd, self.READ_ONLY_MASK) self._pending_connections = {} self._handlers = [] self._next_cleanup = 0 self._required_size = None
def _create_socket(self, host, port): addr = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM) if not addr: raise Exception("Could not translate address '%s:%s'" % (self._host, str(self._port))) server_socket = socket.socket(addr[0][0], addr[0][1], addr[0][2]) utils.closeOnExec(server_socket.fileno()) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(addr[0][4]) server_socket.listen(5) if self._sslctx: server_socket = SSLServerSocket(raw=server_socket, certfile=self._sslctx.cert_file, keyfile=self._sslctx.key_file, ca_certs=self._sslctx.ca_cert) server_socket.setblocking(0) return server_socket
def _createXMLRPCServer(self): """ Create xml-rpc server over http or https. """ HTTP_HEADER_FLOWID = "FlowID" threadLocal = self.cif.threadLocal server_address = (self.serverIP, int(self.serverPort)) if self.enableSSL: basehandler = SecureXMLRPCServer.SecureXMLRPCRequestHandler else: basehandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler class RequestHandler(basehandler): # Timeout for the request socket timeout = 60 log = logging.getLogger("BindingXMLRPC.RequestHandler") HEADER_POOL = "Storage-Pool-Id" HEADER_DOMAIN = "Storage-Domain-Id" HEADER_IMAGE = "Image-Id" HEADER_VOLUME = "Volume-Id" HEADER_CONTENT_LENGTH = "content-length" HEADER_CONTENT_TYPE = "content-type" def setup(self): threadLocal.client = self.client_address[0] threadLocal.server = self.request.getsockname()[0] return basehandler.setup(self) def do_PUT(self): try: contentLength = self.headers.getheader(self.HEADER_CONTENT_LENGTH) if not contentLength: self.send_error(httplib.LENGTH_REQUIRED, "missing content length") return try: contentLength = int(contentLength) except ValueError: self.send_error(httplib.BAD_REQUEST, "invalid content length %r" % contentLength) return # Required headers spUUID = self.headers.getheader(self.HEADER_POOL) sdUUID = self.headers.getheader(self.HEADER_DOMAIN) imgUUID = self.headers.getheader(self.HEADER_IMAGE) if not all((spUUID, sdUUID, imgUUID)): self.send_error( httplib.BAD_REQUEST, "missing or empty required header(s):" " spUUID=%s sdUUID=%s imgUUID=%s" % (spUUID, sdUUID, imgUUID), ) return # Optional headers volUUID = self.headers.getheader(self.HEADER_VOLUME) uploadFinishedEvent = threading.Event() def upload_finished(): uploadFinishedEvent.set() methodArgs = {"fileObj": self.rfile, "contentLength": contentLength} image = API.Image(imgUUID, spUUID, sdUUID) response = image.downloadFromStream(methodArgs, upload_finished, volUUID) while not uploadFinishedEvent.is_set(): uploadFinishedEvent.wait() json_response = json.dumps(response) self.send_response(httplib.OK) self.send_header(self.HEADER_CONTENT_TYPE, "application/json") self.send_header(self.HEADER_CONTENT_LENGTH, len(json_response)) self.end_headers() self.wfile.write(json_response) except socket.timeout: self.send_error(httplib.REQUEST_TIMEOUT, "request timeout") except Exception: self.send_error(httplib.INTERNAL_SERVER_ERROR, "error during execution", exc_info=True) def send_error(self, error, message, exc_info=False): try: self.log.error(message, exc_info=exc_info) self.send_response(error) self.end_headers() except Exception: self.log.error("failed to return response", exc_info=True) def parse_request(self): r = basehandler.parse_request(self) threadLocal.flowID = self.headers.get(HTTP_HEADER_FLOWID) return r def finish(self): basehandler.finish(self) threadLocal.client = None threadLocal.server = None threadLocal.flowID = None if sys.version_info[:2] == (2, 6): # Override BaseHTTPServer.BaseRequestHandler implementation to # avoid pointless and slow attempt to get the fully qualified # host name from the client address. This method is not used # any more in Python 2.7. def address_string(self): return self.client_address[0] if self.enableSSL: KEYFILE, CERTFILE, CACERT = self._getKeyCertFilenames() server = SecureXMLRPCServer.SecureThreadedXMLRPCServer( server_address, keyfile=KEYFILE, certfile=CERTFILE, ca_certs=CACERT, timeout=self.serverRespTimeout, requestHandler=RequestHandler, ) else: server = utils.SimpleThreadedXMLRPCServer(server_address, requestHandler=RequestHandler, logRequests=True) utils.closeOnExec(server.socket.fileno()) return server
def _createXMLRPCServer(self): """ Create xml-rpc server over http or https. """ HTTP_HEADER_FLOWID = "FlowID" threadLocal = self.cif.threadLocal server_address = (self.serverIP, int(self.serverPort)) if self.enableSSL: basehandler = SecureXMLRPCServer.SecureXMLRPCRequestHandler else: basehandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler class RequestHandler(basehandler): # Timeout for the request socket timeout = 60 log = logging.getLogger("BindingXMLRPC.RequestHandler") HEADER_POOL = 'Storage-Pool-Id' HEADER_DOMAIN = 'Storage-Domain-Id' HEADER_IMAGE = 'Image-Id' HEADER_VOLUME = 'Volume-Id' HEADER_TASK_ID = 'Task-Id' HEADER_SIZE = 'Size' HEADER_CONTENT_LENGTH = 'content-length' HEADER_CONTENT_TYPE = 'content-type' class RequestException(): def __init__(self, httpStatusCode, errorMessage): self.httpStatusCode = httpStatusCode self.errorMessage = errorMessage def setup(self): threadLocal.client = self.client_address[0] threadLocal.server = self.request.getsockname()[0] return basehandler.setup(self) def do_GET(self): try: length = self._getIntHeader(self.HEADER_SIZE, httplib.BAD_REQUEST) img = self._createImage() startEvent = threading.Event() methodArgs = {'fileObj': self.wfile, 'length': length} uploadFinishedEvent, operationEndCallback = \ self._createEventWithCallback() # Optional header volUUID = self.headers.getheader(self.HEADER_VOLUME) response = img.uploadToStream(methodArgs, operationEndCallback, startEvent, volUUID) if response['status']['code'] == 0: self.send_response(httplib.OK) self.send_header(self.HEADER_CONTENT_TYPE, 'application/octet-stream') self.send_header(self.HEADER_CONTENT_LENGTH, length) self.send_header(self.HEADER_TASK_ID, response['uuid']) self.end_headers() startEvent.set() self._waitForEvent(uploadFinishedEvent) else: self._send_error_response(response) except self.RequestException as e: # This is an expected exception, so traceback is unneeded self.send_error(e.httpStatusCode, e.errorMessage) except Exception: self.send_error(httplib.INTERNAL_SERVER_ERROR, "error during execution", exc_info=True) def do_PUT(self): try: contentLength = self._getIntHeader( self.HEADER_CONTENT_LENGTH, httplib.LENGTH_REQUIRED) img = self._createImage() methodArgs = { 'fileObj': self.rfile, 'length': contentLength } uploadFinishedEvent, operationEndCallback = \ self._createEventWithCallback() # Optional header volUUID = self.headers.getheader(self.HEADER_VOLUME) response = img.downloadFromStream(methodArgs, operationEndCallback, volUUID) if response['status']['code'] == 0: while not uploadFinishedEvent.is_set(): uploadFinishedEvent.wait() self.send_response(httplib.OK) self.send_header(self.HEADER_TASK_ID, response['uuid']) self.end_headers() else: self._send_error_response(response) except self.RequestException as e: self.send_error(e.httpStatusCode, e.errorMessage) except Exception: self.send_error(httplib.INTERNAL_SERVER_ERROR, "error during execution", exc_info=True) def _createImage(self): # Required headers spUUID = self.headers.getheader(self.HEADER_POOL) sdUUID = self.headers.getheader(self.HEADER_DOMAIN) imgUUID = self.headers.getheader(self.HEADER_IMAGE) if not all((spUUID, sdUUID, imgUUID)): raise self.RequestException( httplib.BAD_REQUEST, "missing or empty required header(s):" " spUUID=%s sdUUID=%s imgUUID=%s" % (spUUID, sdUUID, imgUUID)) return API.Image(imgUUID, spUUID, sdUUID) @staticmethod def _createEventWithCallback(): operationFinishedEvent = threading.Event() def setCallback(): operationFinishedEvent.set() return operationFinishedEvent, setCallback @staticmethod def _waitForEvent(event): while not event.is_set(): event.wait() def _getIntHeader(self, headerName, missingError): value = self.headers.getheader(headerName) if not value: raise self.RequestException( missingError, "missing header %s" % headerName) try: value = int(value) except ValueError: raise self.RequestException( httplib.BAD_REQUEST, "invalid header value %r" % value) return value def send_error(self, error, message, exc_info=False): try: self.log.error(message, exc_info=exc_info) self.send_response(error) self.end_headers() except Exception: self.log.error("failed to return response", exc_info=True) def _send_error_response(self, response): self.send_response(httplib.INTERNAL_SERVER_ERROR) json_response = json.dumps(response) self.send_header(self.HEADER_CONTENT_TYPE, 'application/json') self.send_header(self.HEADER_CONTENT_LENGTH, len(json_response)) self.end_headers() self.wfile.write(json_response) def parse_request(self): r = basehandler.parse_request(self) threadLocal.flowID = self.headers.get(HTTP_HEADER_FLOWID) return r def finish(self): basehandler.finish(self) threadLocal.client = None threadLocal.server = None threadLocal.flowID = None if sys.version_info[:2] == (2, 6): # Override BaseHTTPServer.BaseRequestHandler implementation to # avoid pointless and slow attempt to get the fully qualified # host name from the client address. This method is not used # any more in Python 2.7. def address_string(self): return self.client_address[0] if self.enableSSL: KEYFILE, CERTFILE, CACERT = self._getKeyCertFilenames() server = SecureXMLRPCServer.SecureThreadedXMLRPCServer( server_address, keyfile=KEYFILE, certfile=CERTFILE, ca_certs=CACERT, timeout=self.serverRespTimeout, requestHandler=RequestHandler) else: server = utils.SimpleThreadedXMLRPCServer( server_address, requestHandler=RequestHandler, logRequests=True) utils.closeOnExec(server.socket.fileno()) return server
def _createXMLRPCServer(self): """ Create xml-rpc server over http or https. """ HTTP_HEADER_FLOWID = "FlowID" threadLocal = self.cif.threadLocal server_address = (self.serverIP, int(self.serverPort)) if self.enableSSL: basehandler = SecureXMLRPCServer.SecureXMLRPCRequestHandler else: basehandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler class RequestHandler(basehandler): # Timeout for the request socket timeout = 60 log = logging.getLogger("BindingXMLRPC.RequestHandler") HEADER_POOL = 'Storage-Pool-Id' HEADER_DOMAIN = 'Storage-Domain-Id' HEADER_IMAGE = 'Image-Id' HEADER_VOLUME = 'Volume-Id' HEADER_TASK_ID = 'Task-Id' HEADER_SIZE = 'Size' HEADER_CONTENT_LENGTH = 'content-length' HEADER_CONTENT_TYPE = 'content-type' class RequestException(): def __init__(self, httpStatusCode, errorMessage): self.httpStatusCode = httpStatusCode self.errorMessage = errorMessage def setup(self): threadLocal.client = self.client_address[0] threadLocal.server = self.request.getsockname()[0] return basehandler.setup(self) def do_GET(self): try: length = self._getIntHeader(self.HEADER_SIZE, httplib.BAD_REQUEST) img = self._createImage() startEvent = threading.Event() methodArgs = {'fileObj': self.wfile, 'length': length} uploadFinishedEvent, operationEndCallback = \ self._createEventWithCallback() # Optional header volUUID = self.headers.getheader(self.HEADER_VOLUME) response = img.uploadToStream(methodArgs, operationEndCallback, startEvent, volUUID) if response['status']['code'] == 0: self.send_response(httplib.OK) self.send_header(self.HEADER_CONTENT_TYPE, 'application/octet-stream') self.send_header(self.HEADER_CONTENT_LENGTH, length) self.send_header(self.HEADER_TASK_ID, response['uuid']) self.end_headers() startEvent.set() self._waitForEvent(uploadFinishedEvent) else: self._send_error_response(response) except self.RequestException as e: # This is an expected exception, so traceback is unneeded self.send_error(e.httpStatusCode, e.errorMessage) except Exception: self.send_error(httplib.INTERNAL_SERVER_ERROR, "error during execution", exc_info=True) def do_PUT(self): try: contentLength = self._getIntHeader( self.HEADER_CONTENT_LENGTH, httplib.LENGTH_REQUIRED) img = self._createImage() methodArgs = {'fileObj': self.rfile, 'length': contentLength} uploadFinishedEvent, operationEndCallback = \ self._createEventWithCallback() # Optional header volUUID = self.headers.getheader(self.HEADER_VOLUME) response = img.downloadFromStream(methodArgs, operationEndCallback, volUUID) if response['status']['code'] == 0: while not uploadFinishedEvent.is_set(): uploadFinishedEvent.wait() self.send_response(httplib.OK) self.send_header(self.HEADER_TASK_ID, response['uuid']) self.end_headers() else: self._send_error_response(response) except self.RequestException as e: self.send_error(e.httpStatusCode, e.errorMessage) except Exception: self.send_error(httplib.INTERNAL_SERVER_ERROR, "error during execution", exc_info=True) def _createImage(self): # Required headers spUUID = self.headers.getheader(self.HEADER_POOL) sdUUID = self.headers.getheader(self.HEADER_DOMAIN) imgUUID = self.headers.getheader(self.HEADER_IMAGE) if not all((spUUID, sdUUID, imgUUID)): raise self.RequestException( httplib.BAD_REQUEST, "missing or empty required header(s):" " spUUID=%s sdUUID=%s imgUUID=%s" % (spUUID, sdUUID, imgUUID)) return API.Image(imgUUID, spUUID, sdUUID) @staticmethod def _createEventWithCallback(): operationFinishedEvent = threading.Event() def setCallback(): operationFinishedEvent.set() return operationFinishedEvent, setCallback @staticmethod def _waitForEvent(event): while not event.is_set(): event.wait() def _getIntHeader(self, headerName, missingError): value = self.headers.getheader( headerName) if not value: raise self.RequestException( missingError, "missing header %s" % headerName) try: value = int(value) except ValueError: raise self.RequestException( httplib.BAD_REQUEST, "invalid header value %r" % value) return value def send_error(self, error, message, exc_info=False): try: self.log.error(message, exc_info=exc_info) self.send_response(error) self.end_headers() except Exception: self.log.error("failed to return response", exc_info=True) def _send_error_response(self, response): self.send_response(httplib.INTERNAL_SERVER_ERROR) json_response = json.dumps(response) self.send_header(self.HEADER_CONTENT_TYPE, 'application/json') self.send_header(self.HEADER_CONTENT_LENGTH, len(json_response)) self.end_headers() self.wfile.write(json_response) def parse_request(self): r = basehandler.parse_request(self) threadLocal.flowID = self.headers.get(HTTP_HEADER_FLOWID) return r def finish(self): basehandler.finish(self) threadLocal.client = None threadLocal.server = None threadLocal.flowID = None if sys.version_info[:2] == (2, 6): # Override BaseHTTPServer.BaseRequestHandler implementation to # avoid pointless and slow attempt to get the fully qualified # host name from the client address. This method is not used # any more in Python 2.7. def address_string(self): return self.client_address[0] if self.enableSSL: KEYFILE, CERTFILE, CACERT = self._getKeyCertFilenames() server = SecureXMLRPCServer.SecureThreadedXMLRPCServer( server_address, keyfile=KEYFILE, certfile=CERTFILE, ca_certs=CACERT, timeout=self.serverRespTimeout, requestHandler=RequestHandler) else: server = utils.SimpleThreadedXMLRPCServer( server_address, requestHandler=RequestHandler, logRequests=True) utils.closeOnExec(server.socket.fileno()) return server