Saggi Mizrahi has uploaded a new change for review.
Change subject: [WIP] EVENTS ......................................................................
[WIP] EVENTS
Change-Id: Id27b5ca1773139932eb5cb16921d5abec4991c5e Signed-off-by: Saggi Mizrahi smizrahi@redhat.com --- M lib/stompClient.py M lib/vdsm/config.py.in M lib/vdsm/sslutils.py M lib/yajsonrpc/betterAsyncore.py M lib/yajsonrpc/stomp.py M lib/yajsonrpc/stompReactor.py M tests/jsonRpcHelper.py M tests/jsonRpcTests.py M tests/miscTests.py M tests/protocoldetectorTests.py M vdsm.spec.in M vdsm/API.py M vdsm/clientIF.py M vdsm/protocoldetector.py M vdsm/rpc/BindingJsonRpc.py 15 files changed, 336 insertions(+), 141 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/69/38069/1
diff --git a/lib/stompClient.py b/lib/stompClient.py index d3cd0ab..5a6d7f5 100644 --- a/lib/stompClient.py +++ b/lib/stompClient.py @@ -1,6 +1,12 @@ #!/usr/bin/python import yajsonrpc as yjrpc -import yajsonrpc.stompReactor as sr +from yajsonrpc.stompReactor import ( + _DEFAULT_REQUEST_DESTINATION, + _DEFAULT_RESPONSE_DESTINATION, + ClientRpcTransportAdapter, + ServerRpcContextAdapter, + StompReactor, +) import socket from threading import Thread, Lock import time @@ -14,7 +20,7 @@ if _reactor is None: with _reactorLock: if _reactor is None: - _reactor = sr.StompReactor() + _reactor = StompReactor() t = Thread(target=_reactor.process_requests) t.setDaemon(True) t.start() @@ -42,95 +48,38 @@ t.setDaemon(True) t.start() sub = stomp_client.subscribe( - sr._DEFAULT_REQUEST_DESTINATION, + _DEFAULT_REQUEST_DESTINATION, message_handler=ServerRpcContextAdapter.subscription_handler(server) ) server._sub_ = sub return server
-class ServerRpcContextAdapter(object): - @classmethod - def subscription_handler(cls, server): - def handler(sub, frame): - server.queueRequest( - ( - ServerRpcContextAdapter(sub.client, frame), - frame.body - ) - ) - - return handler - - def __init__(self, client, request_frame): - self._client = client - self._reply_to = request_frame.headers.get('reply-to', None) - - def get_local_address(self, *args, **kwargs): - return "" - - def send(self, data): - if self._reply_to is None: - return - - self._client.send( - self._reply_to, - data, - { - "content-type": "application/json", - } - ) - - -class ClientRpcTransportAdapter(object): - def __init__(self, sub, destination, client): - self._sub = sub - sub.set_message_handler(self._handle_message) - self._destination = destination - self._client = client - self._message_handler = lambda arg: None - - def setMessageHandler(self, handler): - self._message_handler = handler - - def send(self, data): - headers = { - "content-type": "application/json", - "reply-to": self._sub.destination, - } - self._client.send( - data, - self._destination, - headers, - ) - - def _handle_message(self, sub, frame): - self._message_handler((self, frame.body)) - - def close(self): - self._sub.unsubscribe() - - def connect(address): sock = socket.create_connection(address) reactor = get_reactor() stomp_client = reactor.createClient(sock) - subscription = stomp_client.subscribe(sr._DEFAULT_RESPONSE_DESTINATIOM) + subscription = stomp_client.subscribe( + _DEFAULT_RESPONSE_DESTINATION, + sub_id="__vdsm_fake_broker__", + ) client = yjrpc.JsonRpcClient( ClientRpcTransportAdapter( subscription, - sr._DEFAULT_REQUEST_DESTINATION, + _DEFAULT_REQUEST_DESTINATION, stomp_client, ) ) return client
-BROKER_ADDRESS = ("127.0.0.1", 5445) +BROKER_ADDRESS = ("127.0.0.1", 54321)
-server = dummy_server(BROKER_ADDRESS) +# server = dummy_server(BROKER_ADDRESS)
time.sleep(2)
client = connect(BROKER_ADDRESS) -client.callMethod("echo", ["123"], 1) +client.callMethod("Host.ping", [], 1) +client.callMethod("Host.ping", [], 1) +client.callMethod("Host.ping", [], 1) diff --git a/lib/vdsm/config.py.in b/lib/vdsm/config.py.in index 94c6782..fb0150b 100644 --- a/lib/vdsm/config.py.in +++ b/lib/vdsm/config.py.in @@ -325,6 +325,20 @@
('guests_gateway_ip', '', None),
+ ('broker_address', '127.0.0.1', + 'Address where the broker is listening at. Use an empty string ' + 'for none'), + + ('broker_port', '5445', + 'Port where the broker is listening at.'), + + ('request_queues', + 'jms.topic.vdsm_requests, jms.topic.vdsm_irs_requests', + 'Queues to subscribe to for RPC requests'), + + ('topic_prefix', 'jms.topic.', + 'Prefix to use for events'), + ]),
# Section: [devel] diff --git a/lib/vdsm/sslutils.py b/lib/vdsm/sslutils.py index 74555ee..6568842 100644 --- a/lib/vdsm/sslutils.py +++ b/lib/vdsm/sslutils.py @@ -35,7 +35,7 @@ class SSLSocket(object): def __init__(self, connection): self.connection = connection - self._data = None + self._data = ""
def gettimeout(self): return self.connection.socket.gettimeout() @@ -57,12 +57,14 @@ def read(self, size=4096, flag=None): result = None if flag == socket.MSG_PEEK: - self._data = self.connection.read(size) + bytes_left = size - len(self._data) + if bytes_left > 0: + self._data += self.connection.read(bytes_left) result = self._data else: if self._data: result = self._data - self._data = None + self._data = "" else: result = self.connection.read(size) return result diff --git a/lib/yajsonrpc/betterAsyncore.py b/lib/yajsonrpc/betterAsyncore.py index af88877..8656df8 100644 --- a/lib/yajsonrpc/betterAsyncore.py +++ b/lib/yajsonrpc/betterAsyncore.py @@ -18,14 +18,17 @@ # while enabling compositing instead of inheritance. import asyncore import socket -import types from errno import EWOULDBLOCK +import types
from vdsm.infra.eventfd import EventFD
class Dispatcher(asyncore.dispatcher): def __init__(self, impl=None, sock=None, map=None): + # This has to be done before the super initialization because + # dispatcher implements __getattr__. + self.__impl = None asyncore.dispatcher.__init__(self, sock=sock, map=map) if impl is not None: self.switch_implementation(impl) @@ -82,8 +85,9 @@
Note that this value is a reccomendation only. """ + impl = self.__impl return getattr( - self.__impl, + impl, "next_check_interval", lambda d: None )(self) @@ -100,7 +104,7 @@ self.handle_read()
if hasattr(self.socket, "pending"): - while self.socket.pending() > 0: + while self.socket.pending() > 0 and self.connected: self.handle_read()
def recv(self, buffer_size): @@ -115,7 +119,9 @@ return data except socket.error, why: # winsock sometimes raises ENOTCONN - if why.args[0] in asyncore._DISCONNECTED: + if why.args[0] == EWOULDBLOCK: + return None + elif why.args[0] in asyncore._DISCONNECTED: self.handle_close() return '' else: diff --git a/lib/yajsonrpc/stomp.py b/lib/yajsonrpc/stomp.py index a3d63f3..cf24a7f 100644 --- a/lib/yajsonrpc/stomp.py +++ b/lib/yajsonrpc/stomp.py @@ -16,11 +16,12 @@ import logging import os import socket -from threading import Timer from uuid import uuid4 from collections import deque
import re + +FAKE_SUB_ID = "__vdsm_fake_broker__"
_RE_ESCAPE_SEQUENCE = re.compile(r"\(.)")
@@ -75,7 +76,10 @@
class StompError(RuntimeError): def __init__(self, frame): - RuntimeError.__init__(self, frame.body) + self.frame = frame + super(RuntimeError, self).__init__( + self.body, + )
class _HeartBeatFrame(object): @@ -441,10 +445,9 @@ def _process_message(self, frame, dispatcher): sub_id = frame.headers.get(Headers.SUBSCRIPTION) if sub_id is None: - self.log.warning( - "Got message without a subscription" - ) - return + # This is actually an error, but because of the fake broker we + # injects a fake sub id + sub_id = "__vdsm_fake_broker__"
sub = self._subscriptions.get(sub_id) if sub is None: @@ -464,7 +467,8 @@
def send(self, destination, data="", headers=None): final_headers = {"destination": destination} - final_headers.update(headers) + if headers is not None: + final_headers.update(headers) self.queue_frame(Frame( Command.SEND, final_headers, @@ -552,8 +556,3 @@ {"id": str(subid)}) client.put(frame) self._valid = False - - def __del__(self): - # Using a timer because unsubscribe action might involve taking locks. - if self._valid: - Timer(0, self.unsubscribe) diff --git a/lib/yajsonrpc/stompReactor.py b/lib/yajsonrpc/stompReactor.py index 5a1b595..44fbcbb 100644 --- a/lib/yajsonrpc/stompReactor.py +++ b/lib/yajsonrpc/stompReactor.py @@ -20,15 +20,17 @@
from betterAsyncore import Dispatcher, Reactor from vdsm.sslutils import SSLSocket +from . import ( + JsonRpcClient, + JsonRpcServer, +)
_STATE_LEN = "Waiting for message length" _STATE_MSG = "Waiting for message"
-_DEFAULT_RESPONSE_DESTINATIOM = "jms.topic.vdsm_legacy_responses" +_DEFAULT_RESPONSE_DESTINATION = "jms.topic.vdsm_legacy_responses" _DEFAULT_REQUEST_DESTINATION = "jms.topic.vdsm_legacy_requests" - -_FAKE_SUB_ID = "__vdsm_fake_broker__"
def parseHeartBeatHeader(v): @@ -177,13 +179,16 @@ def check_read(self): self._stompConn._dispatcher.handle_read_event()
- def send(self, message): + def send( + self, + message, + destination=_DEFAULT_RESPONSE_DESTINATION, + ): self.log.debug("Sending response") res = stomp.Frame( stomp.Command.MESSAGE, { - stomp.Headers.DESTINATION: _DEFAULT_RESPONSE_DESTINATIOM, - stomp.Headers.SUBSCRIPTION: _FAKE_SUB_ID, + stomp.Headers.DESTINATION: destination, stomp.Headers.CONTENT_TYPE: "application/json", }, message @@ -325,3 +330,101 @@ dispatcher.del_channel() self.json_binding.add_socket(self._reactor, client_socket) self.log.debug("Stomp detected from %s", socket_address) + + +class ServerRpcContextAdapter(object): + @classmethod + def subscription_handler(cls, server): + def handler(sub, frame): + server.queueRequest( + ( + ServerRpcContextAdapter(sub.client, frame), + frame.body + ) + ) + + return handler + + def __init__(self, client, request_frame): + self._client = client + self._reply_to = request_frame.headers.get('reply-to', None) + + def get_local_address(self, *args, **kwargs): + return "" + + def send(self, data): + if self._reply_to is None: + return + + self._client.send( + self._reply_to, + data, + { + "content-type": "application/json", + } + ) + + +class ClientRpcTransportAdapter(object): + def __init__(self, sub, destination, client): + self._sub = sub + sub.set_message_handler(self._handle_message) + self._destination = destination + self._client = client + self._message_handler = lambda arg: None + + def setMessageHandler(self, handler): + self._message_handler = handler + + def send(self, data): + headers = { + "content-type": "application/json", + "reply-to": self._sub.destination, + } + self._client.send( + data, + self._destination, + headers, + ) + + def _handle_message(self, sub, frame): + self._message_handler((self, frame.body)) + + def close(self): + self._sub.unsubscribe() + + +def StompRpcClient( + stomp_client, + request_queue, + response_queue +): + sub_id = None + if request_queue == stomp.FAKE_SUB_ID: + sub_id = stomp.FAKE_SUB_ID + + return JsonRpcClient( + ClientRpcTransportAdapter( + stomp_client.subscribe(response_queue, sub_id=sub_id), + request_queue, + stomp_client, + ) + ) + + +def StompRpcServer( + bridge, + stomp_client, + request_queue, +): + server = JsonRpcServer( + bridge, + ) + + sub = stomp_client.subscribe( + request_queue, + message_handler=ServerRpcContextAdapter.subscription_handler(server) + ) + + server._sub_ = sub + return server diff --git a/tests/jsonRpcHelper.py b/tests/jsonRpcHelper.py index b3eb1fd..2fb7cfb 100644 --- a/tests/jsonRpcHelper.py +++ b/tests/jsonRpcHelper.py @@ -27,9 +27,17 @@ from itertools import product from M2Crypto import SSL from rpc.BindingXMLRPC import BindingXMLRPC, XmlDetector -from yajsonrpc.stompReactor import StompDetector +from yajsonrpc.betterAsyncore import ( + Reactor, +) +from yajsonrpc.stompReactor import ( + StompDetector, + StompRpcClient, +) +from yajsonrpc.stomp import ( + FAKE_SUB_ID, +) from protocoldetector import MultiProtocolAcceptor -from yajsonrpc import JsonRpcClient from rpc.BindingJsonRpc import BindingJsonRpc from sslhelper import DEAFAULT_SSL_CONTEXT
@@ -60,7 +68,13 @@ @contextmanager def constructAcceptor(log, ssl, jsonBridge): sslctx = DEAFAULT_SSL_CONTEXT if ssl else None - acceptor = MultiProtocolAcceptor("127.0.0.1", 0, sslctx) + reactor = Reactor() + acceptor = MultiProtocolAcceptor( + reactor, + "127.0.0.1", + 0, + sslctx, + ) cif = FakeClientIf()
xml_binding = BindingXMLRPC(cif, cif.log) @@ -73,8 +87,10 @@ stompDetector = StompDetector(json_binding) acceptor.add_detector(stompDetector)
- thread = threading.Thread(target=acceptor.serve_forever, - name='Detector thread') + thread = threading.Thread( + target=reactor.process_requests, + name='Detector thread', + ) thread.setDaemon(True) thread.start()
@@ -103,9 +119,12 @@ reactor = handler._reactor
if not client: - client = lambda client_socket: ( - JsonRpcClient(reactor.createClient(client_socket)) - ) + def client(client_socket): + return StompRpcClient( + reactor.createClient(client_socket), + FAKE_SUB_ID, + FAKE_SUB_ID, + )
def clientFactory(): return client(create_socket( diff --git a/tests/jsonRpcTests.py b/tests/jsonRpcTests.py index 230b61a..3254393 100644 --- a/tests/jsonRpcTests.py +++ b/tests/jsonRpcTests.py @@ -83,12 +83,7 @@ @contextmanager def _client(self, clientFactory): client = clientFactory() - client.setTimeout(CALL_TIMEOUT) - client.connect() - try: - yield client - finally: - client.close() + yield client
@MonkeyPatch(clientIF, 'getInstance', getInstance) @permutations(PERMUTATIONS) diff --git a/tests/miscTests.py b/tests/miscTests.py index 1fa572e..f98f539 100644 --- a/tests/miscTests.py +++ b/tests/miscTests.py @@ -991,6 +991,7 @@ openFds = openFdNum() self.testStdOut() gc.collect() + print gc.garbage self.assertEquals(len(gc.garbage), 0) self.assertEquals(openFdNum(), openFds)
diff --git a/tests/protocoldetectorTests.py b/tests/protocoldetectorTests.py index ea64619..c64a1e2 100644 --- a/tests/protocoldetectorTests.py +++ b/tests/protocoldetectorTests.py @@ -23,9 +23,12 @@ import ssl import threading import time -from contextlib import contextmanager, closing +from contextlib import contextmanager
import protocoldetector +from yajsonrpc.betterAsyncore import ( + Reactor, +)
from vdsm import sslutils from sslhelper import KEY_FILE, CRT_FILE @@ -59,12 +62,13 @@
def run(): try: - assert client_socket.gettimeout() is None - rfile = client_socket.makefile('rb', -1) - with closing(rfile): - request = rfile.readline() - response = self.response(request) - client_socket.sendall(response) + request = "" + while "\n" not in request: + request += dispatcher.recv(1024) + + response = self.response(request) + client_socket.setblocking(1) + client_socket.sendall(response) finally: client_socket.shutdown(socket.SHUT_RDWR) client_socket.close() @@ -182,14 +186,14 @@
def check_slow_client(self, use_ssl): with self.connect(use_ssl) as client: - time.sleep(self.acceptor.CLEANUP_INTERVAL - self.GRACETIME) + time.sleep(self.acceptor._handshake_timeout - self.GRACETIME) data = "echo let me in\n" client.sendall(data) self.assertEqual(client.recv(self.BUFSIZE), data)
def check_very_slow_client(self, use_ssl): with self.connect(use_ssl) as client: - time.sleep(self.acceptor.CLEANUP_INTERVAL * 2 + self.GRACETIME) + time.sleep(self.acceptor._handshake_timeout * 2 + self.GRACETIME) client.sendall("echo too slow probably\n") self.check_disconnected(client)
@@ -204,12 +208,18 @@ # Helpers
def start_acceptor(self, use_ssl): - self.acceptor = TestingAcceptor( - '127.0.0.1', 0, sslctx=self.SSLCTX if use_ssl else None) + self.reactor = Reactor() + self.acceptor = protocoldetector.MultiProtocolAcceptor( + self.reactor, + '127.0.0.1', + 0, + sslctx=self.SSLCTX if use_ssl else None + ) + self.acceptor._handshake_timeout = 1 self.acceptor.add_detector(Echo()) self.acceptor.add_detector(Uppercase()) - self.acceptor_address = self.acceptor._socket.getsockname() - t = threading.Thread(target=self.acceptor.serve_forever) + self.acceptor_address = self.acceptor._acceptor.socket.getsockname() + t = threading.Thread(target=self.reactor.process_requests) t.deamon = True t.start()
diff --git a/vdsm.spec.in b/vdsm.spec.in index 0740530..845ddf0 100644 --- a/vdsm.spec.in +++ b/vdsm.spec.in @@ -1606,6 +1606,7 @@ %{python_sitelib}/yajsonrpc/stompReactor.py*
%files infra +%{python_sitelib}/%{vdsm_name}/infra/eventfd/__init__.py* %{python_sitelib}/%{vdsm_name}/infra/filecontrol/__init__.py* %{python_sitelib}/%{vdsm_name}/infra/sigutils/__init__.py* %{python_sitelib}/%{vdsm_name}/infra/zombiereaper/__init__.py* diff --git a/vdsm/API.py b/vdsm/API.py index 42c471e..fdf2c62 100644 --- a/vdsm/API.py +++ b/vdsm/API.py @@ -1267,6 +1267,9 @@ def ping(self): "Ping the server. Useful for tests" updateTimestamp() + n = self._cif.create_notification("vdsm.ping") + n.emit(pinged=True) + return {'status': doneCode}
def getRoute(self, ip): @@ -1286,7 +1289,6 @@ c = caps.get() c['netConfigDirty'] = str(self._cif._netConfigDirty) c = hooks.after_get_caps(c) - return {'status': doneCode, 'info': c}
def getHardwareInfo(self): diff --git a/vdsm/clientIF.py b/vdsm/clientIF.py index d29f8c2..46e7f41 100644 --- a/vdsm/clientIF.py +++ b/vdsm/clientIF.py @@ -23,6 +23,8 @@ import time import threading import uuid +import socket +import json from functools import partial from weakref import proxy
@@ -54,6 +56,35 @@ _glusterEnabled = True except ImportError: _glusterEnabled = False + +from yajsonrpc.betterAsyncore import ( + Reactor, +) + +from yajsonrpc.stompReactor import ( + StompClient, + StompRpcServer, +) + + +class Notification(object): + def __init__(self, event_id, cb): + self._event_id = event_id + self._cb = cb + + def emit(self, **kwargs): + notification = json.dumps( + { + 'jsonrpc': '2.0', + 'method': self._event_id, + 'params': kwargs, + } + ) + + self._cb( + notification, + self._event_id + )
class clientIF(object): @@ -87,6 +118,7 @@ self._generationID = str(uuid.uuid4()) self.mom = None self.bindings = {} + self._clients = [] if _glusterEnabled: self.gluster = gapi.GlusterApi(self, log) else: @@ -109,9 +141,11 @@
host = config.get('addresses', 'management_ip') port = config.getint('addresses', 'management_port') + self._createReactor() self._createAcceptor(host, port) self._prepareXMLRPCBinding() self._prepareJSONRPCBinding() + self._connectToBroker() except: self.log.error('failed to init clientIF, ' 'shutting down storage dispatcher') @@ -124,6 +158,21 @@ @property def ready(self): return (self.irs is None or self.irs.ready) and not self._recovery + + def create_notification(self, event_id): + prefix = config.get('addresses', 'topic_prefix') + return Notification( + prefix + event_id, + self._send_notification, + ) + + def _send_notification(self, message, destination): + if self._broker_client: + self._broker_client.send(message, destination) + + self.log.warn("@@@@@") + for client in self._clients[:]: + client.send(message, destination)
def contEIOVms(self, sdUUID, isDomainStateValid): # This method is called everytime the onDomainStateChange @@ -158,10 +207,46 @@ cls._instance = clientIF(irs, log) return cls._instance
+ def _createReactor(self): + self._reactor = Reactor() + def _createAcceptor(self, host, port): sslctx = self._createSSLContext()
- self._acceptor = MultiProtocolAcceptor(host, port, sslctx) + self._acceptor = MultiProtocolAcceptor( + self._reactor, + host, + port, + sslctx + ) + + def _connectToBroker(self): + broker_address = config.get('addresses', 'broker_address') + broker_port = config.getint('addresses', 'broker_port') + request_queues = config.get('addresses', 'request_queues') + self._broker_client = None + if broker_address: + sslctx = self._createSSLContext() + sock = socket.socket() + sock.connect((broker_address, broker_port)) + if sslctx: + sock = sslctx.wrapSocket(sock) + + stomp_client = StompClient(sock, self._reactor) + subs = [] + for destination in request_queues.split(","): + destination = destination.strip() + if destination: + subs.append( + StompRpcServer( + self.bindings['jsonrpc'].server, + stomp_client, + destination, + ) + ) + + self._subscriptions = subs + self._broker_client = stomp_client
def _createSSLContext(self): sslctx = None @@ -200,7 +285,7 @@ 'Please make sure it is installed.') else: bridge = Bridge.DynamicBridge() - json_binding = BindingJsonRpc(bridge) + json_binding = BindingJsonRpc(bridge, self._clients) self.bindings['jsonrpc'] = json_binding stomp_detector = StompDetector(json_binding) self._acceptor.add_detector(stomp_detector) @@ -243,8 +328,10 @@ def start(self): for binding in self.bindings.values(): binding.start() - self.thread = threading.Thread(target=self._acceptor.serve_forever, - name='Detector thread') + self.thread = threading.Thread( + target=self._reactor.process_requests, + name='Reactor thread' + ) self.thread.setDaemon(True) self.thread.start()
diff --git a/vdsm/protocoldetector.py b/vdsm/protocoldetector.py index 76d5a00..20a0b41 100644 --- a/vdsm/protocoldetector.py +++ b/vdsm/protocoldetector.py @@ -23,11 +23,9 @@
from M2Crypto import SSL
-from vdsm.utils import traceback import vdsm.infra.filecontrol as filecontrol from yajsonrpc.betterAsyncore import ( Dispatcher, - Reactor, )
from vdsm.utils import ( @@ -48,8 +46,6 @@ filecontrol.set_close_on_exec(server_socket.fileno()) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(addr[0][4]) - - server_socket.setblocking(0) return server_socket
@@ -75,6 +71,7 @@ except socket.error: pass
+ client.setblocking(0) self.log.info("Accepting connection from %s:%d", *client.getpeername()) self._dispatcher_factory(client)
@@ -97,8 +94,16 @@ sock = dispatcher.socket try: data = sock.recv(self._required_size, socket.MSG_PEEK) - except socket.error: + except socket.error, why: + if why.args[0] == socket.EWOULDBLOCK: + return + dispatcher.handle_error() + return + + if monotonic_time() > self._give_up_at: + self.log.debug("Timed out while waiting for data") + dispatcher.close() return
if len(data) < self._required_size: @@ -210,13 +215,15 @@
def __init__( self, + reactor, host, port, sslctx=None, ssl_hanshake_timeout=SSL_HANDSHAKE_TIMEOUT, ): self._sslctx = sslctx - self._reactor = Reactor() + self._reactor = reactor + sock = _create_socket(host, port) self._host, self._port = sock.getsockname() self.log.info("Listening at %s:%d", self._host, self._port) @@ -261,13 +268,6 @@ )
return dispatcher - - @traceback(on=log.name) - def serve_forever(self): - self.log.debug("Running") - required_size = max(h.REQUIRED_SIZE for h in self._handlers) - self.log.debug("Using required_size=%d", required_size) - self._reactor.process_requests()
def add_detector(self, detector): self.log.debug("Adding detector %s", detector) diff --git a/vdsm/rpc/BindingJsonRpc.py b/vdsm/rpc/BindingJsonRpc.py index a5b5b4a..eeea8ba 100644 --- a/vdsm/rpc/BindingJsonRpc.py +++ b/vdsm/rpc/BindingJsonRpc.py @@ -29,14 +29,21 @@ class BindingJsonRpc(object): log = logging.getLogger('BindingJsonRpc')
- def __init__(self, bridge): + def __init__(self, bridge, clients=None): self._server = JsonRpcServer(bridge, _simpleThreadFactory) + self._clients = clients self._reactors = [] + + @property + def server(self): + return self._server
def add_socket(self, reactor, client_socket): reactor.createListener(client_socket, self._onAccept)
def _onAccept(self, listener, client): + if self._clients is not None: + self._clients.append(client) client.setMessageHandler(self._server.queueRequest)
def createStompReactor(self):
automation@ovirt.org has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 1:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 1:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el7_created/494/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc21_created/486... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/15996/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/1052... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/15195/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16166/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created_staging/972/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/103... : SUCCESS
Piotr Kliczewski has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 1: Code-Review-1
(14 comments)
http://gerrit.ovirt.org/#/c/38069/1/lib/stompClient.py File lib/stompClient.py:
Line 74: Line 75: Line 76: BROKER_ADDRESS = ("127.0.0.1", 54321) Line 77: Line 78: # server = dummy_server(BROKER_ADDRESS) Do we need this comment? Line 79: Line 80: time.sleep(2) Line 81: Line 82: client = connect(BROKER_ADDRESS)
http://gerrit.ovirt.org/#/c/38069/1/lib/vdsm/config.py.in File lib/vdsm/config.py.in:
Line 324: ('management_ip', '0.0.0.0', 'Set to "::" to listen on IPv6.'), Line 325: Line 326: ('guests_gateway_ip', '', None), Line 327: Line 328: ('broker_address', '127.0.0.1', Do we really bind to loopback? Line 329: 'Address where the broker is listening at. Use an empty string ' Line 330: 'for none'), Line 331: Line 332: ('broker_port', '5445',
http://gerrit.ovirt.org/#/c/38069/1/lib/yajsonrpc/stompReactor.py File lib/yajsonrpc/stompReactor.py:
Line 28: _STATE_LEN = "Waiting for message length" Line 29: _STATE_MSG = "Waiting for message" Line 30: Line 31: Line 32: _DEFAULT_RESPONSE_DESTINATION = "jms.topic.vdsm_legacy_responses" How that will work with current 3.5? Line 33: _DEFAULT_REQUEST_DESTINATION = "jms.topic.vdsm_legacy_requests" Line 34: Line 35: Line 36: def parseHeartBeatHeader(v):
Line 348: def __init__(self, client, request_frame): Line 349: self._client = client Line 350: self._reply_to = request_frame.headers.get('reply-to', None) Line 351: Line 352: def get_local_address(self, *args, **kwargs): Do we need it? Line 353: return "" Line 354: Line 355: def send(self, data): Line 356: if self._reply_to is None:
http://gerrit.ovirt.org/#/c/38069/1/tests/miscTests.py File tests/miscTests.py:
Line 990: gc.collect() Line 991: openFds = openFdNum() Line 992: self.testStdOut() Line 993: gc.collect() Line 994: print gc.garbage what is the value of printing it? Line 995: self.assertEquals(len(gc.garbage), 0) Line 996: self.assertEquals(openFdNum(), openFds) Line 997: Line 998:
http://gerrit.ovirt.org/#/c/38069/1/tests/protocoldetectorTests.py File tests/protocoldetectorTests.py:
Line 66: while "\n" not in request: Line 67: request += dispatcher.recv(1024) Line 68: Line 69: response = self.response(request) Line 70: client_socket.setblocking(1) Why do we want to block? Line 71: client_socket.sendall(response) Line 72: finally: Line 73: client_socket.shutdown(socket.SHUT_RDWR) Line 74: client_socket.close()
Line 214: '127.0.0.1', Line 215: 0, Line 216: sslctx=self.SSLCTX if use_ssl else None Line 217: ) Line 218: self.acceptor._handshake_timeout = 1 why do we need this timeout? Line 219: self.acceptor.add_detector(Echo()) Line 220: self.acceptor.add_detector(Uppercase()) Line 221: self.acceptor_address = self.acceptor._acceptor.socket.getsockname() Line 222: t = threading.Thread(target=self.reactor.process_requests)
http://gerrit.ovirt.org/#/c/38069/1/vdsm.spec.in File vdsm.spec.in:
Line 1605: %{python_sitelib}/yajsonrpc/stomp.py* Line 1606: %{python_sitelib}/yajsonrpc/stompReactor.py* Line 1607: Line 1608: %files infra Line 1609: %{python_sitelib}/%{vdsm_name}/infra/eventfd/__init__.py* Is it part of this patch? Line 1610: %{python_sitelib}/%{vdsm_name}/infra/filecontrol/__init__.py* Line 1611: %{python_sitelib}/%{vdsm_name}/infra/sigutils/__init__.py* Line 1612: %{python_sitelib}/%{vdsm_name}/infra/zombiereaper/__init__.py* Line 1613: %{python_sitelib}/%{vdsm_name}/infra/__init__.py*
http://gerrit.ovirt.org/#/c/38069/1/vdsm/API.py File vdsm/API.py:
Line 1263: message = out + err Line 1264: return {'status': {'code': rc, 'message': message}, Line 1265: 'power': 'unknown', 'operationStatus': 'initiated'} Line 1266: Line 1267: def ping(self): This verb is used by setupNetworks. I do not think that we want to change its behavior. Line 1268: "Ping the server. Useful for tests" Line 1269: updateTimestamp() Line 1270: n = self._cif.create_notification("vdsm.ping") Line 1271: n.emit(pinged=True)
http://gerrit.ovirt.org/#/c/38069/1/vdsm/clientIF.py File vdsm/clientIF.py:
Line 66: StompRpcServer, Line 67: ) Line 68: Line 69: Line 70: class Notification(object): This should not be part of this module Line 71: def __init__(self, event_id, cb): Line 72: self._event_id = event_id Line 73: self._cb = cb Line 74:
Line 70: class Notification(object): Line 71: def __init__(self, event_id, cb): Line 72: self._event_id = event_id Line 73: self._cb = cb Line 74: why do we want to have 2 step notification sending? Line 75: def emit(self, **kwargs): Line 76: notification = json.dumps( Line 77: { Line 78: 'jsonrpc': '2.0',
Line 169: def _send_notification(self, message, destination): Line 170: if self._broker_client: Line 171: self._broker_client.send(message, destination) Line 172: Line 173: self.log.warn("@@@@@") We should remove this warn. Line 174: for client in self._clients[:]: Line 175: client.send(message, destination) Line 176: Line 177: def contEIOVms(self, sdUUID, isDomainStateValid):
Line 171: self._broker_client.send(message, destination) Line 172: Line 173: self.log.warn("@@@@@") Line 174: for client in self._clients[:]: Line 175: client.send(message, destination) Why do we want to send notifications to all the clients? Line 176: Line 177: def contEIOVms(self, sdUUID, isDomainStateValid): Line 178: # This method is called everytime the onDomainStateChange Line 179: # event is emitted, this event is emitted even when a domain goes
http://gerrit.ovirt.org/#/c/38069/1/vdsm/protocoldetector.py File vdsm/protocoldetector.py:
Line 48 Line 49 Line 50 Line 51 Line 52 do we really want to block?
Yaniv Bronhaim has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 1:
(2 comments)
https://gerrit.ovirt.org/#/c/38069/1/vdsm/clientIF.py File vdsm/clientIF.py:
Line 212: Line 213: def _createAcceptor(self, host, port): Line 214: sslctx = self._createSSLContext() Line 215: Line 216: self._acceptor = MultiProtocolAcceptor( having reactor instance in multiProtocolAcceptor should be one separate patch. please split Line 217: self._reactor, Line 218: host, Line 219: port, Line 220: sslctx
Line 330: binding.start() Line 331: self.thread = threading.Thread( Line 332: target=self._reactor.process_requests, Line 333: name='Reactor thread' Line 334: ) not related Line 335: self.thread.setDaemon(True) Line 336: self.thread.start() Line 337: Line 338: def _getUUIDSpecPath(self, uuid):
Piotr Kliczewski has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 1:
(2 comments)
https://gerrit.ovirt.org/#/c/38069/1/vdsm/clientIF.py File vdsm/clientIF.py:
Line 212: Line 213: def _createAcceptor(self, host, port): Line 214: sslctx = self._createSSLContext() Line 215: Line 216: self._acceptor = MultiProtocolAcceptor(
having reactor instance in multiProtocolAcceptor should be one separate pat
Done Line 217: self._reactor, Line 218: host, Line 219: port, Line 220: sslctx
Line 330: binding.start() Line 331: self.thread = threading.Thread( Line 332: target=self._reactor.process_requests, Line 333: name='Reactor thread' Line 334: )
not related
It is related since io loop is not in acceptor but was moved to reactor so we need to change it. Line 335: self.thread.setDaemon(True) Line 336: self.thread.start() Line 337: Line 338: def _getUUIDSpecPath(self, uuid):
automation@ovirt.org has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 2:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
automation@ovirt.org has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 3:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 3:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16354/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/15554/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16524/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 4:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 4:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16462/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16633/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_el_gerrit/15662/ : FAILURE
Piotr Kliczewski has posted comments on this change.
Change subject: [WIP] EVENTS ......................................................................
Patch Set 4: Verified-1
jsonrpc code is not working for el6
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 5:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 5:
Verified that communication with engine 3.5 works but not checked event infrastructure yet.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 5:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16670/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16842/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 6:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 6:
Rebased, communication with engine 3.5 works but events not verified yet.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 6:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16764/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16936/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 7:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 7: Verified+1
Rebased, added event test and verified with engine 3.5.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 8:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 8: Verified+1
Updaed __init__.py by moving part of change from broker patch which belong to this patch. Verified with engine 3.5.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 9:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 7:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16796/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16968/ : FAILURE
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 8:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16798/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16970/ : SUCCESS
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 9:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16801/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/16973/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 10:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 10:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16873/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17045/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 10:
(1 comment)
https://gerrit.ovirt.org/#/c/38069/10/vdsm/clientIF.py File vdsm/clientIF.py:
Line 145: Line 146: def _send_notification(self, message, destination): Line 147: json_binding = self.bindings['jsonrpc'] Line 148: server = json_binding.getStompReactor().server Line 149: server.send(message) We have two problems here. One is that we need to jumps through a few hoops, most notably keep ClientIF references around, just to send notification. Moreover, ClientIF doesn't fill the right place for notifications. But let's save this for a later moment
The second is that I'm under the impression that most often client code just wants to do one notification and forget about it. No need to keep around state, thus no need to have a create_* (and keep some state around)
So, a function like
def notify(self, event_id, **kwargs): event = Notification(event_id, self._send_notification) event.emit(**kwargs)
to be used like (see https://gerrit.ovirt.org/#/c/38937/1/vdsm/virt/vm.py)
# this is inside Vm class self.cif.notify(self.id='UP')
seems bot nicer to use and shorter to implement.
What do you think? Line 150: Line 151: def contEIOVms(self, sdUUID, isDomainStateValid): Line 152: # This method is called everytime the onDomainStateChange Line 153: # event is emitted, this event is emitted even when a domain goes
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 10:
(1 comment)
https://gerrit.ovirt.org/#/c/38069/10/vdsm/clientIF.py File vdsm/clientIF.py:
Line 145: Line 146: def _send_notification(self, message, destination): Line 147: json_binding = self.bindings['jsonrpc'] Line 148: server = json_binding.getStompReactor().server Line 149: server.send(message)
We have two problems here.
We need a means to give people ability to send notifications. ClientIF is now used by most of the code which makes it ugly but good trash can. I am open for other commonly used parts of the code which could hold events infra code for sending.
I agree with you and we should simplify the code. Will work on it. Line 150: Line 151: def contEIOVms(self, sdUUID, isDomainStateValid): Line 152: # This method is called everytime the onDomainStateChange Line 153: # event is emitted, this event is emitted even when a domain goes
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 11:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16964/
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 11:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 11: Verified+1
Rebased, fixed comments, verified with latest engine (master).
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 11:
Build Started (2/2) -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17137/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 11:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/16964/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17137/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 12:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 12:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/17581/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 12:
Build Started (2/2) -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17755/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 12:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/17581/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17755/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 13:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 13:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/17622/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 13:
Build Started (2/2) -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17796/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 13:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/17622/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17796/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 14:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 14:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/17783/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 14:
Build Started (2/2) -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/17954/
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 15:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 15:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/18043/
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 15: Verified+1
Added logging when event sent.
Verified by host deploying vdsm containing all patches from events topic. Storage domain was provisioned and vm was created. Flow of events when changing vm state was observed.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 15:
Build Started (2/2)
0 -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/1272/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 15:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/18043/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/1272/ : 0
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 16:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 16:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/18093/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 16:
Build Started (2/2)
0 -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/1322/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 16:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/18093/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/1322/ : 0
Yaniv Bronhaim has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 16: Code-Review-1
(5 comments)
https://gerrit.ovirt.org/#/c/38069/16/lib/yajsonrpc/stompReactor.py File lib/yajsonrpc/stompReactor.py:
Line 28: _STATE_LEN = "Waiting for message length" Line 29: _STATE_MSG = "Waiting for message" Line 30: Line 31: Line 32: _DEFAULT_RESPONSE_DESTINATION = "jms.topic.vdsm_legacy_responses" fix it separately.
please try to avoid fixing other places in the code in such big, important and very specific patches - it makes the review much harder and the log can confuse others in the future. Line 33: _DEFAULT_REQUEST_DESTINATION = "jms.topic.vdsm_legacy_requests" Line 34: Line 35: Line 36: def parseHeartBeatHeader(v):
Line 335: self._stompConn.connect() Line 336: Line 337: def handle_message(self, sub, frame): Line 338: if self._messageHandler is not None: Line 339: self._messageHandler((self, frame.body)) I knew it :) fix where you introduce it Line 340: Line 341: def setMessageHandler(self, msgHandler): Line 342: self._messageHandler = msgHandler Line 343: self.check_read()
https://gerrit.ovirt.org/#/c/38069/16/vdsm/clientIF.py File vdsm/clientIF.py:
Line 17 Line 18 Line 19 Line 20 Line 21 stick to the patch ...
Line 145: def _send_notification(self, message, destination): Line 146: json_binding = self.bindings['jsonrpc'] Line 147: server = json_binding.getStompReactor().server Line 148: self.log.debug("Sending event %s", message) Line 149: server.send(message) why not
self.bindings['jsonrpc'].getStompReactor().server.send(message)
and log it inside Notification Line 150: Line 151: def contEIOVms(self, sdUUID, isDomainStateValid): Line 152: # This method is called everytime the onDomainStateChange Line 153: # event is emitted, this event is emitted even when a domain goes
https://gerrit.ovirt.org/#/c/38069/16/vdsm/rpc/BindingJsonRpc.py File vdsm/rpc/BindingJsonRpc.py:
Line 39: Line 40: def _onAccept(self, client): Line 41: client.setMessageHandler(self._server.queueRequest) Line 42: Line 43: def getStompReactor(self): make it a property . Line 44: return self._reactor Line 45: Line 46: def start(self): Line 47: t = threading.Thread(target=self._server.serve_requests,
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 16:
(5 comments)
https://gerrit.ovirt.org/#/c/38069/16/lib/yajsonrpc/stompReactor.py File lib/yajsonrpc/stompReactor.py:
Line 28: _STATE_LEN = "Waiting for message length" Line 29: _STATE_MSG = "Waiting for message" Line 30: Line 31: Line 32: _DEFAULT_RESPONSE_DESTINATION = "jms.topic.vdsm_legacy_responses"
fix it separately.
Done Line 33: _DEFAULT_REQUEST_DESTINATION = "jms.topic.vdsm_legacy_requests" Line 34: Line 35: Line 36: def parseHeartBeatHeader(v):
Line 335: self._stompConn.connect() Line 336: Line 337: def handle_message(self, sub, frame): Line 338: if self._messageHandler is not None: Line 339: self._messageHandler((self, frame.body))
I knew it :) fix where you introduce it
Will remove from previous patch. Line 340: Line 341: def setMessageHandler(self, msgHandler): Line 342: self._messageHandler = msgHandler Line 343: self.check_read()
https://gerrit.ovirt.org/#/c/38069/16/vdsm/clientIF.py File vdsm/clientIF.py:
Line 17 Line 18 Line 19 Line 20 Line 21
stick to the patch ...
Done
Line 145: def _send_notification(self, message, destination): Line 146: json_binding = self.bindings['jsonrpc'] Line 147: server = json_binding.getStompReactor().server Line 148: self.log.debug("Sending event %s", message) Line 149: server.send(message)
why not
Done Line 150: Line 151: def contEIOVms(self, sdUUID, isDomainStateValid): Line 152: # This method is called everytime the onDomainStateChange Line 153: # event is emitted, this event is emitted even when a domain goes
https://gerrit.ovirt.org/#/c/38069/16/vdsm/rpc/BindingJsonRpc.py File vdsm/rpc/BindingJsonRpc.py:
Line 39: Line 40: def _onAccept(self, client): Line 41: client.setMessageHandler(self._server.queueRequest) Line 42: Line 43: def getStompReactor(self):
make it a property .
Done Line 44: return self._reactor Line 45: Line 46: def start(self): Line 47: t = threading.Thread(target=self._server.serve_requests,
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 17:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 17: Verified+1
Verified by installing a host, creating vm and seeing events being processed by the engine.
There are some issues noticed after suspending a vm but not related to this changes.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 17:
Build Started (1/2) -> http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/18276/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 17:
Build Started (2/2)
0 -> http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/1506/
oVirt Jenkins CI Server has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 17:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/18276/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/1506/ : 0
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 18:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 19:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Yaniv Bronhaim has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 19: Code-Review-1
(6 comments)
https://gerrit.ovirt.org/#/c/38069/19/lib/yajsonrpc/__init__.py File lib/yajsonrpc/__init__.py:
Line 167: Line 168: return JsonRpcResponse(result, error, reqId) Line 169: Line 170: Line 171: class Notification(object): why don't you comment when you introduce new class. I have no idea where do you plan to use this new class and what its purpose.
if only clientIF uses it why do you need it at all ?
def notify could just compose the json directly with the event id and set the callback Line 172: log = logging.getLogger("jsonrpc.Notification") Line 173: Line 174: def __init__(self, event_id, cb): Line 175: self._event_id = event_id
https://gerrit.ovirt.org/#/c/38069/19/lib/yajsonrpc/stomp.py File lib/yajsonrpc/stomp.py:
Line 75: class StompError(RuntimeError): Line 76: def __init__(self, frame): Line 77: self.frame = frame Line 78: super(RuntimeError, self).__init__( Line 79: self.body, shouldn't it be frame.body? Line 80: ) Line 81: Line 82: Line 83: class _HeartBeatFrame(object):
https://gerrit.ovirt.org/#/c/38069/19/lib/yajsonrpc/stompReactor.py File lib/yajsonrpc/stompReactor.py:
Line 303 Line 304 Line 305 Line 306 Line 307 we don't close the connections anymore? please mention in the comment message what and why you remove things
Line 273: Line 274: def send( Line 275: self, Line 276: message, Line 277: destination=_DEFAULT_RESPONSE_DESTINATION, have a comment that explains what is the default_response_destination when you don't specify destination and what "destination" can be. Line 278: ): Line 279: self.log.debug("Sending response") Line 280: try: Line 281: resp = json.loads(message)
https://gerrit.ovirt.org/#/c/38069/19/vdsm/clientIF.py File vdsm/clientIF.py:
Line 17 Line 18 Line 19 Line 20 Line 21 not related..
https://gerrit.ovirt.org/#/c/38069/19/vdsm/rpc/BindingJsonRpc.py File vdsm/rpc/BindingJsonRpc.py:
Line 31: Line 32: def __init__(self, bridge): Line 33: self._server = JsonRpcServer(bridge, _simpleThreadFactory) Line 34: self._reactor = StompReactor() Line 35: self.startReactor(self._reactor) why do you pass it.. its the class parameter :? Line 36: Line 37: def add_socket(self, reactor, client_socket): Line 38: reactor.createListener(client_socket, self._onAccept) Line 39:
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 19:
(6 comments)
https://gerrit.ovirt.org/#/c/38069/19/lib/yajsonrpc/__init__.py File lib/yajsonrpc/__init__.py:
Line 167: Line 168: return JsonRpcResponse(result, error, reqId) Line 169: Line 170: Line 171: class Notification(object):
why don't you comment when you introduce new class. I have no idea where do
In my opinion here are the details that clientIF should not be aware of. I will document this class. Line 172: log = logging.getLogger("jsonrpc.Notification") Line 173: Line 174: def __init__(self, event_id, cb): Line 175: self._event_id = event_id
https://gerrit.ovirt.org/#/c/38069/19/lib/yajsonrpc/stomp.py File lib/yajsonrpc/stomp.py:
Line 75: class StompError(RuntimeError): Line 76: def __init__(self, frame): Line 77: self.frame = frame Line 78: super(RuntimeError, self).__init__( Line 79: self.body,
shouldn't it be frame.body?
Done Line 80: ) Line 81: Line 82: Line 83: class _HeartBeatFrame(object):
https://gerrit.ovirt.org/#/c/38069/19/lib/yajsonrpc/stompReactor.py File lib/yajsonrpc/stompReactor.py:
Line 303 Line 304 Line 305 Line 306 Line 307
we don't close the connections anymore? please mention in the comment messa
Done
Line 273: Line 274: def send( Line 275: self, Line 276: message, Line 277: destination=_DEFAULT_RESPONSE_DESTINATION,
have a comment that explains what is the default_response_destination when
Done Line 278: ): Line 279: self.log.debug("Sending response") Line 280: try: Line 281: resp = json.loads(message)
https://gerrit.ovirt.org/#/c/38069/19/vdsm/clientIF.py File vdsm/clientIF.py:
Line 17 Line 18 Line 19 Line 20 Line 21
not related..
Done
https://gerrit.ovirt.org/#/c/38069/19/vdsm/rpc/BindingJsonRpc.py File vdsm/rpc/BindingJsonRpc.py:
Line 31: Line 32: def __init__(self, bridge): Line 33: self._server = JsonRpcServer(bridge, _simpleThreadFactory) Line 34: self._reactor = StompReactor() Line 35: self.startReactor(self._reactor)
why do you pass it.. its the class parameter :?
Done Line 36: Line 37: def add_socket(self, reactor, client_socket): Line 38: reactor.createListener(client_socket, self._onAccept) Line 39:
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 20:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 20: Verified+1
Fixed comments, rebased and verified by installing a host and configuring nfs storage domain. Events not tested.
Dan Kenigsberg has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 20:
(2 comments)
https://gerrit.ovirt.org/#/c/38069/20/vdsm/clientIF.py File vdsm/clientIF.py:
Line 16 Line 17 Line 18 Line 19 Line 20 unhelpful...
https://gerrit.ovirt.org/#/c/38069/20/vdsm/rpc/BindingJsonRpc.py File vdsm/rpc/BindingJsonRpc.py:
Line 30: log = logging.getLogger('BindingJsonRpc') Line 31: Line 32: def __init__(self, bridge): Line 33: self._server = JsonRpcServer(bridge, _simpleThreadFactory) Line 34: self._reactor = StompReactor() Allowing only a single reactor is not really related to having events. Please place it in its own patch. Line 35: self.startReactor() Line 36: Line 37: def add_socket(self, reactor, client_socket): Line 38: reactor.createListener(client_socket, self._onAccept)
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 20:
(2 comments)
https://gerrit.ovirt.org/#/c/38069/20/vdsm/clientIF.py File vdsm/clientIF.py:
Line 16 Line 17 Line 18 Line 19 Line 20
unhelpful...
Done
https://gerrit.ovirt.org/#/c/38069/20/vdsm/rpc/BindingJsonRpc.py File vdsm/rpc/BindingJsonRpc.py:
Line 30: log = logging.getLogger('BindingJsonRpc') Line 31: Line 32: def __init__(self, bridge): Line 33: self._server = JsonRpcServer(bridge, _simpleThreadFactory) Line 34: self._reactor = StompReactor()
Allowing only a single reactor is not really related to having events. Plea
Done Line 35: self.startReactor() Line 36: Line 37: def add_socket(self, reactor, client_socket): Line 38: reactor.createListener(client_socket, self._onAccept)
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 21:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 21: Verified+1
Reduced scope, rebased and verified by installing a host and running a vm to see sent events.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 22:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 23:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 23: Verified+1
Verified by vdsm updated and see that there are no issues with communication.
Nir Soffer has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 23:
(8 comments)
https://gerrit.ovirt.org/#/c/38069/23//COMMIT_MSG Commit Message:
Line 8: Line 9: Infrastructure which allows to send events. Line 10: Line 11: Stomp server is no longer responsible for managing connections and all Line 12: the connection life cycle are done in _StompConnection. Is this related to supporting events? how? Line 13: Line 14: Change-Id: Id27b5ca1773139932eb5cb16921d5abec4991c5e Line 15: Signed-off-by: Saggi Mizrahi smizrahi@redhat.com
https://gerrit.ovirt.org/#/c/38069/23/lib/yajsonrpc/__init__.py File lib/yajsonrpc/__init__.py:
Line 100: if method is None: Line 101: raise JsonRpcInvalidRequestError("missing method header", obj) Line 102: Line 103: reqId = obj.get("id") Line 104: # when sending notifications id is not provided Why? How is this change going to effect messages which are not notifications, and are missing an event id? Line 105: Line 106: params = obj.get('params', []) Line 107: if not isinstance(params, (list, dict)): Line 108: raise JsonRpcInvalidRequestError("wrong params type", obj)
Line 184: notification = json.dumps( Line 185: { Line 186: 'jsonrpc': '2.0', Line 187: 'method': self._event_id, Line 188: 'params': kwargs, Why do you call params **kwargs? If an event has params, they should be called params everywhere in the application.
Also, isn't this a standard jsonrpc message? why not have a function creating a new message and use it everywhere?
For example:
def message(method, **params): return { "jsonrpc": "2.0", "method": method, "params": params } Line 189: } Line 190: ) Line 191: Line 192: self.log.debug("Sending event %s", notification)
Line 188: 'params': kwargs, Line 189: } Line 190: ) Line 191: Line 192: self.log.debug("Sending event %s", notification) Is this an event or a notification? Lets use the same term everywhere. Line 193: self._cb(notification) Line 194: Line 195: Line 196: class _JsonRpcClientRequestContext(object):
Line 189: } Line 190: ) Line 191: Line 192: self.log.debug("Sending event %s", notification) Line 193: self._cb(notification) How do you know that self._cb will send the notification/event?
This is a user supplied function, so it can do anything. Why emitting a notification should be done using a user provided callback? Line 194: Line 195: Line 196: class _JsonRpcClientRequestContext(object): Line 197: def __init__(self, requests, callback):
https://gerrit.ovirt.org/#/c/38069/23/lib/yajsonrpc/stomp.py File lib/yajsonrpc/stomp.py:
Line 75: Line 76: class StompError(RuntimeError): Line 77: def __init__(self, frame): Line 78: self.frame = frame Line 79: super(RuntimeError, self).__init__(self.frame.body) How is this change related to having events? Line 80: Line 81: Line 82: class _HeartBeatFrame(object): Line 83: def encode(self):
https://gerrit.ovirt.org/#/c/38069/23/lib/yajsonrpc/stompreactor.py File lib/yajsonrpc/stompreactor.py:
Line 304 Line 305 Line 306 Line 307 Line 308 Why did you remove the close() interface?
https://gerrit.ovirt.org/#/c/38069/23/vdsm/clientIF.py File vdsm/clientIF.py:
Line 142: self._send_notification, Line 143: ) Line 144: notification.emit(**kwargs) Line 145: Line 146: def _send_notification(self, message, destination): What is the unused "destination" parameter? Line 147: self.bindings['jsonrpc'].reactor.server.send(message) Line 148: Line 149: def contEIOVms(self, sdUUID, isDomainStateValid): Line 150: # This method is called everytime the onDomainStateChange
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 23:
(8 comments)
https://gerrit.ovirt.org/#/c/38069/23//COMMIT_MSG Commit Message:
Line 8: Line 9: Infrastructure which allows to send events. Line 10: Line 11: Stomp server is no longer responsible for managing connections and all Line 12: the connection life cycle are done in _StompConnection.
Is this related to supporting events? how?
It is refactoring needed to provide events. Line 13: Line 14: Change-Id: Id27b5ca1773139932eb5cb16921d5abec4991c5e Line 15: Signed-off-by: Saggi Mizrahi smizrahi@redhat.com
https://gerrit.ovirt.org/#/c/38069/23/lib/yajsonrpc/__init__.py File lib/yajsonrpc/__init__.py:
Line 100: if method is None: Line 101: raise JsonRpcInvalidRequestError("missing method header", obj) Line 102: Line 103: reqId = obj.get("id") Line 104: # when sending notifications id is not provided
Why? How is this change going to effect messages which are not notification
please take a look at jsonrpc 2.0 spec. Line 105: Line 106: params = obj.get('params', []) Line 107: if not isinstance(params, (list, dict)): Line 108: raise JsonRpcInvalidRequestError("wrong params type", obj)
Line 184: notification = json.dumps( Line 185: { Line 186: 'jsonrpc': '2.0', Line 187: 'method': self._event_id, Line 188: 'params': kwargs,
Why do you call params **kwargs? If an event has params, they should be cal
it is a notification not the standard message. Please take a look at jsonrpc 2.0 spec. Line 189: } Line 190: ) Line 191: Line 192: self.log.debug("Sending event %s", notification)
Line 188: 'params': kwargs, Line 189: } Line 190: ) Line 191: Line 192: self.log.debug("Sending event %s", notification)
Is this an event or a notification? Lets use the same term everywhere.
High level name that we use is events. Notification format is used from the spec. Line 193: self._cb(notification) Line 194: Line 195: Line 196: class _JsonRpcClientRequestContext(object):
Line 189: } Line 190: ) Line 191: Line 192: self.log.debug("Sending event %s", notification) Line 193: self._cb(notification)
How do you know that self._cb will send the notification/event?
I will update docstring. Line 194: Line 195: Line 196: class _JsonRpcClientRequestContext(object): Line 197: def __init__(self, requests, callback):
https://gerrit.ovirt.org/#/c/38069/23/lib/yajsonrpc/stomp.py File lib/yajsonrpc/stomp.py:
Line 75: Line 76: class StompError(RuntimeError): Line 77: def __init__(self, frame): Line 78: self.frame = frame Line 79: super(RuntimeError, self).__init__(self.frame.body)
How is this change related to having events?
Will separate to another patch. Line 80: Line 81: Line 82: class _HeartBeatFrame(object): Line 83: def encode(self):
https://gerrit.ovirt.org/#/c/38069/23/lib/yajsonrpc/stompreactor.py File lib/yajsonrpc/stompreactor.py:
Line 304 Line 305 Line 306 Line 307 Line 308
Why did you remove the close() interface?
I gave an explanation in commit message.
https://gerrit.ovirt.org/#/c/38069/23/vdsm/clientIF.py File vdsm/clientIF.py:
Line 142: self._send_notification, Line 143: ) Line 144: notification.emit(**kwargs) Line 145: Line 146: def _send_notification(self, message, destination):
What is the unused "destination" parameter?
It is a leftover. Will fix. We have destination configured now in config.py. Line 147: self.bindings['jsonrpc'].reactor.server.send(message) Line 148: Line 149: def contEIOVms(self, sdUUID, isDomainStateValid): Line 150: # This method is called everytime the onDomainStateChange
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 24:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 24: Verified+1
Verified by running vdsm with the latest engine change. Tested vm status changes: - starting a vm - suspending a vm - resuming a vm
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 24:
Build failure not related to this patch.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 25:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 26:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 26:
Build failure not related to this change.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 27:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 28:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 28: Verified+1
Verified with the engine containing event changes to see that events are send on vm status changes.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 29:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 30:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Yaniv Bronhaim has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 30: Code-Review+1
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31: Verified+1
Verified with latest engine containing event changes.
Yaniv Bronhaim has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31: Code-Review+1
Yeela Kaplan has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31: Code-Review-1
(4 comments)
https://gerrit.ovirt.org/#/c/38069/31/lib/yajsonrpc/stompreactor.py File lib/yajsonrpc/stompreactor.py:
Line 288: subscribed /s/subscribes which subscribed/subscribers
Line 285: self._reactor) Line 286: Line 287: """ Line 288: Sends message to all subscribes which subscribed to destination. Line 289: If destination is not provided we use default destination. destination part is quite self explanatory, I think we can remove second line of comment and let the code explain itself... Line 290: """ Line 291: def send(self, message, destination=_DEFAULT_RESPONSE_DESTINATION): Line 292: self.log.debug("Sending response") Line 293: try:
https://gerrit.ovirt.org/#/c/38069/31/tests/jsonRpcHelper.py File tests/jsonRpcHelper.py:
Line 93: Line 94: json_binding = BindingJsonRpc(jsonBridge) Line 95: json_binding.start() Line 96: Line 97: cif.json_binding = json_binding I think it might be better to add a ctor to FakeClientIf and pass it the json_binding.
so cif will only be created after json_binding. This allows us to remove line #48 that instantiates cif json_binding to None which seems redundant. Line 98: jsonBridge.cif = cif Line 99: Line 100: stompDetector = StompDetector(json_binding) Line 101: acceptor.add_detector(stompDetector)
https://gerrit.ovirt.org/#/c/38069/31/vdsm/clientIF.py File vdsm/clientIF.py:
Line 138: def notify(self, event_id, **kwargs): Line 139: """ Line 140: Send notification using provided subscription id as Line 141: event_id and a dictionary as event body. Before sending Line 142: there is notify_time added on top level to the dictionary. Here also, I think that there are too many details. Following will be enough: Send notification using provided subscription id and event body.
Whoever needs more details should read Notification code in yajsonrpc. Line 143: """ Line 144: notification = Notification( Line 145: event_id, Line 146: self._send_notification,
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31:
(4 comments)
https://gerrit.ovirt.org/#/c/38069/31/lib/yajsonrpc/stompreactor.py File lib/yajsonrpc/stompreactor.py:
Line 288: subscribed
/s/subscribes which subscribed/subscribers
Done
Line 285: self._reactor) Line 286: Line 287: """ Line 288: Sends message to all subscribes which subscribed to destination. Line 289: If destination is not provided we use default destination.
destination part is quite self explanatory, I think we can remove second li
Done Line 290: """ Line 291: def send(self, message, destination=_DEFAULT_RESPONSE_DESTINATION): Line 292: self.log.debug("Sending response") Line 293: try:
https://gerrit.ovirt.org/#/c/38069/31/tests/jsonRpcHelper.py File tests/jsonRpcHelper.py:
Line 93: Line 94: json_binding = BindingJsonRpc(jsonBridge) Line 95: json_binding.start() Line 96: Line 97: cif.json_binding = json_binding
I think it might be better to add a ctor to FakeClientIf and pass it the js
Done Line 98: jsonBridge.cif = cif Line 99: Line 100: stompDetector = StompDetector(json_binding) Line 101: acceptor.add_detector(stompDetector)
https://gerrit.ovirt.org/#/c/38069/31/vdsm/clientIF.py File vdsm/clientIF.py:
Line 138: def notify(self, event_id, **kwargs): Line 139: """ Line 140: Send notification using provided subscription id as Line 141: event_id and a dictionary as event body. Before sending Line 142: there is notify_time added on top level to the dictionary.
Here also,
The comment was requested so I think it should stay as it is. Line 143: """ Line 144: notification = Notification( Line 145: event_id, Line 146: self._send_notification,
Yaniv Bronhaim has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31: Code-Review-1
I see that masayag tries to pass over the clientIF instance to ifcfg.py which under network module to be able to call the send event function. In vm.py this implementation fits better (https://gerrit.ovirt.org/#/c/38937/22) because the vm instance is initialized through clientIF - but obviously we need to be able to send event from each module . We need to find better location for holding the reactor . Pioter, please give another alternative for exposing the single reactor and we'll discuss about it - for now I prefer not to leave it as in this patch
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31:
Yaniv, how the code which is used to trigger an event is related to the location of reactor?
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 31:
(1 comment)
https://gerrit.ovirt.org/#/c/38069/31/lib/yajsonrpc/stompreactor.py File lib/yajsonrpc/stompreactor.py:
Line 288: subscribed
Done
Actually it is OK. The messages are sent to subscribers that subscribed. Will updated to have "that" there.
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 32:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Piotr Kliczewski has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 32: Verified+1
Verified by updating vdsm and creating new vm.
Yaniv Bronhaim has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 32: Code-Review+1
I don't have better ideas except another singleton for now, and I understand that this clientIF craziness is already discussed . I still want to see a usage of :
import clientIF (relatively to where we are) clientIF.getInstance().notify(123, "buho")
that's actually tested.
Dan Kenigsberg has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 32: Code-Review+2
Let it be
Dan Kenigsberg has submitted this change and it was merged.
Change subject: jsonrpc: events ......................................................................
jsonrpc: events
Infrastructure which allows to send events.
Stomp server is no longer responsible for managing connections and all the connection life cycle are done in _StompConnection.
Change-Id: Id27b5ca1773139932eb5cb16921d5abec4991c5e Signed-off-by: Saggi Mizrahi smizrahi@redhat.com Signed-off-by: pkliczewski piotr.kliczewski@gmail.com Reviewed-on: https://gerrit.ovirt.org/38069 Reviewed-by: Yaniv Bronhaim ybronhei@redhat.com Continuous-Integration: Jenkins CI Reviewed-by: Dan Kenigsberg danken@redhat.com --- M lib/yajsonrpc/__init__.py M lib/yajsonrpc/stompreactor.py M tests/jsonRpcHelper.py M tests/jsonRpcTests.py M vdsm/clientIF.py 5 files changed, 95 insertions(+), 14 deletions(-)
Approvals: Piotr Kliczewski: Verified Yaniv Bronhaim: Looks good to me, but someone else must approve Jenkins CI: Passed CI tests Dan Kenigsberg: Looks good to me, approved
automation@ovirt.org has posted comments on this change.
Change subject: jsonrpc: events ......................................................................
Patch Set 33:
* Update tracker::IGNORE, no Bug-Url found * Set MODIFIED::IGNORE, no Bug-Url found.
vdsm-patches@lists.fedorahosted.org