Alon Bar-Lev has posted comments on this change.

Change subject: fklsnr: Introduce standalone fence_kdump listener
......................................................................


Patch Set 6:

(29 comments)

http://gerrit.ovirt.org/#/c/27201/6/ovirt-engine.spec.in
File ovirt-engine.spec.in:

Line 404: Requires:     %{name} = %{version}-%{release}
Line 405: Requires:     %{name}-lib >= %{version}-%{release}
Line 406: Requires:     java
Line 407: Requires:     logrotate
Line 408: Requires:     python-dateutil
as far as I can see this is not required.
Line 409: Requires:     python-psycopg2
Line 410: 
Line 411: %if %{ovirt_install_systemd}
Line 412: Requires(post):               systemd


http://gerrit.ovirt.org/#/c/27201/6/packaging/services/ovirt-fence-kdump-listener/db.py
File packaging/services/ovirt-fence-kdump-listener/db.py:

Line 50:         self._connection = None
Line 51: 
Line 52:     def __enter__(self):
Line 53:         self._open_connection()
Line 54:         return self
return instance of dao? danken would have commented that with should return a 
different object than self :)

but if no dao then ok.
Line 55: 
Line 56:     def __exit__(self, exc_type, exc_value, traceback):
Line 57:         self._connection.close()
Line 58: 


Line 102:                 pass
Line 103:         return valid
Line 104: 
Line 105:     def get_connection(self):
Line 106:         if not self._connection_valid():
you probably need to close connection?
Line 107:             self._open_connection()
Line 108: 
Line 109:         return self._connection
Line 110: 


Line 115: 
Line 116:     def __init__(
Line 117:             self,
Line 118:             connection_manager):
Line 119:         super(EngineDao, self).__init__()
): -> next line
Line 120:         self._conn_mgr = connection_manager
Line 121: 
Line 122:     def _execute(
Line 123:             self,


Line 122:     def _execute(
Line 123:             self,
Line 124:             statement,
Line 125:             args=None,
Line 126:     ):
I would have expected _execute be on the connection class.

dao should expose only logical methods.
Line 127:         ret = []
Line 128:         self.logger.debug(
Line 129:             "Statement: '%s', Args: {%s}",
Line 130:             statement,


Line 191:             statement="""
Line 192:                 INSERT INTO fence_kdump_messages (vds_id, received, 
address,
Line 193:                                                   status)
Line 194:                     VALUES (%(vds_id)s, %(received)s, %(address)s,
Line 195:                             %(status)s)
can you please use the same notation of coding for sql statements?

 insert into fence_kdump_messages (
     vds_id,
     received,
     address,
     status
 ) values (
     %(vds_id)s,
     %(received)s,
     %(address)s,
     %(status)s
 )
Line 196:             """,
Line 197:             args={
Line 198:                 'vds_id': vds_id,
Line 199:                 'received': received,


http://gerrit.ovirt.org/#/c/27201/6/packaging/services/ovirt-fence-kdump-listener/listener.py
File packaging/services/ovirt-fence-kdump-listener/listener.py:

Line 13: # limitations under the License.
Line 14: 
Line 15: import binascii
Line 16: import datetime
Line 17: import dateutil.tz
no need
Line 18: import gettext
Line 19: import socket
Line 20: import struct
Line 21: 


Line 32: 
Line 33:     # fence_kdump message version 1
Line 34:     _MSG_V1_SIZE = 8
Line 35:     _MSG_V1_VERSION = 1
Line 36:     _MSG_V1_MAGIC = 456141376
will hex make it easier to understand?
Line 37: 
Line 38:     def __init__(
Line 39:             self,
Line 40:             bind,


Line 53:             self._sessionExpirationTime
Line 54:         )
Line 55:         self._lastHeartbeat = None
Line 56:         self._lastWakeup = None
Line 57:         self._bufsize = 0x10000
can you please move this also as a constant while we at it... it can be much 
lower if you know the max size of packet.
Line 58:         self._sessions = {}
Line 59:         self._populate_sessions()
Line 60: 
Line 61:     def __enter__(self):


Line 66:     def __exit__(self, exc_type, exc_value, traceback):
Line 67:         self._socket.close()
Line 68: 
Line 69:     def _now(self):
Line 70:         return datetime.datetime.now(dateutil.tz.tzutc())
datetime.datetime.utcnow()
Line 71: 
Line 72:     def _total_seconds(self, td):
Line 73:         return (
Line 74:             td.microseconds + (td.seconds + td.days * 24 * 3600) * 
10**6


Line 71: 
Line 72:     def _total_seconds(self, td):
Line 73:         return (
Line 74:             td.microseconds + (td.seconds + td.days * 24 * 3600) * 
10**6
Line 75:         ) / 10**6
please use the magic of:

 time.mktime(datetime.datetime.now().timetuple())
Line 76: 
Line 77:     def _interval_finished(self, interval, last):
Line 78:         return (
Line 79:             last is None


Line 76: 
Line 77:     def _interval_finished(self, interval, last):
Line 78:         return (
Line 79:             last is None
Line 80:             or self._total_seconds(self._now() - last) >= interval
please move the or to suffix of previous line
Line 81:         )
Line 82: 
Line 83:     def _recvfrom(self):
Line 84:         ret = (None, None)


Line 113:             else:
Line 114:                 entry = self._sessions.get(address[0])
Line 115:                 if entry is None:
Line 116:                     entry = {
Line 117:                         'vds_id': 
self._dao.get_host_with_address(address[0]),
please do not access dao here, move all application specific into the handle 
message at state initial, here just leave the session tracking and status.
Line 118:                         'status': self.SESSION_STATE_INITIAL,
Line 119:                         'address': address,
Line 120:                         'received': None,
Line 121:                     }


Line 135:         return (
Line 136:             message
Line 137:             and len(message) >= self._MSG_V1_SIZE
Line 138:             and _parse_number(message) == self._MSG_V1_MAGIC
Line 139:             and _parse_number(message, 4) == self._MSG_V1_VERSION
please put boolean conditions at end of previous line.

now... that I see this... I think you can do:

 PREFIX = '01020333112'.decode('hex')

 return (
     len(message) == self._MSG_V1_SIZE and
     message.encode[:len(self.PREFIX)] == self.PREFIX
 )
Line 140:         )
Line 141: 
Line 142:     def _handle_message(self, entry, message):
Line 143:         if not self._verify_message(message):


Line 148:                     msg=binascii.hexlify(message),
Line 149:                     address=entry['address'][0],
Line 150:                 )
Line 151:             )
Line 152:             return
please do not return at middle of functions, throw exception.
Line 153: 
Line 154:         if not entry['vds_id']:
Line 155:             self.logger.warning(
Line 156:                 _(


Line 163: 
Line 164:         try:
Line 165:             self._dao.create_fence_kdump_message(
Line 166:                 vds_id=entry['vds_id'],
Line 167:                 received=received,
I am unsure why you cannot use now() within database, why do you care of exact 
time within python, all we need is trigger keep alive
Line 168:                 address=entry['address'],
Line 169:                 status=entry['status'],
Line 170:             )
Line 171: 


Line 169:                 status=entry['status'],
Line 170:             )
Line 171: 
Line 172:             # record successfully saved in db, update in memory cache
Line 173:             entry['received'] = received
I am unsure I understand why you cannot first update memory then sync into 
database.
Line 174:             if entry['status'] == self.SESSION_STATE_INITIAL:
Line 175:                 self.logger.info(
Line 176:                     _(
Line 177:                         "Host '{vds_id}' with address '{address}' 
started "


Line 181:                         address=entry['address'][0],
Line 182:                     )
Line 183:                 )
Line 184:                 entry['status'] = self.SESSION_STATE_DUMPING
Line 185:                 self._sessions[entry['address'][0]] = entry
why do you need to touch _Sessions in this function? entry is already within 
session.

also I am unsure why you drop the port.
Line 186: 
Line 187:             elif entry['status'] == self.SESSION_STATE_DUMPING:
Line 188:                 self.logger.debug(
Line 189:                     'dumping %s',


Line 204:             self.logger.debug('Exception',  exc_info=True)
Line 205: 
Line 206:     def _house_keeping_sessions(self):
Line 207:         for session in self._sessions.values():
Line 208:             received = self._now()
please move out the now from loop
Line 209: 
Line 210:             if self._interval_finished(
Line 211:                     interval=self._sessionExpirationTime,
Line 212:                     last=session['received']


Line 208:             received = self._now()
Line 209: 
Line 210:             if self._interval_finished(
Line 211:                     interval=self._sessionExpirationTime,
Line 212:                     last=session['received']
too much indent
Line 213:             ):
Line 214:                 new_state = self.SESSION_STATE_CLOSED
Line 215:                 try:
Line 216:                     self._dao.create_fence_kdump_message(


Line 220:                         status=new_state,
Line 221:                     )
Line 222: 
Line 223:                     # record successfully saved in db, update in 
memory cache
Line 224:                     session['status'] = new_state
this will only create infinite loop and make more and more attempts to access 
database as session will be kept expired.

if database is down there is no reason to continue to listening to dumps.

and if you think it is that critical... we need to modify the model.

instead of using the dao directly, to have a list of dao commands.

and at housekeeping try to process as many of these as we can.

however, this also suggest that you load into memory the entire host list with 
all addresses, as you cannot assume that on session initiation you will have 
database connection, right?
Line 225:                     session['received'] = received
Line 226:                     self.logger.info(
Line 227:                         _(
Line 228:                             "Host '{vds_id}' with address '{address}' 
"


Line 261:             try:
Line 262:                 new_heartbeat = self._now()
Line 263: 
Line 264:                 self._dao.update_heartbeat(
Line 265:                     heartbeat=new_heartbeat,
please use database now() no need to involve python time
Line 266:                 )
Line 267: 
Line 268:                 self._lastHeartbeat = new_heartbeat
Line 269:                 self.logger.debug('heartbeat')


Line 280:             # if record is saved to db, in memory cache status
Line 281:             # is always 'dumping'
Line 282:             record['status'] = self.SESSION_STATE_DUMPING
Line 283:             # address is stored as string, convert back to tuple
Line 284:             record['address'] = tuple(record['address'])
return tuple from dao, as you already have conversion there?
Line 285:             self._sessions[record['address'][0]] = record
Line 286: 
Line 287: 


Line 281:             # is always 'dumping'
Line 282:             record['status'] = self.SESSION_STATE_DUMPING
Line 283:             # address is stored as string, convert back to tuple
Line 284:             record['address'] = tuple(record['address'])
Line 285:             self._sessions[record['address'][0]] = record
not sure why this is needed.
Line 286: 
Line 287: 


http://gerrit.ovirt.org/#/c/27201/6/packaging/services/ovirt-fence-kdump-listener/ovirt-fence-kdump-listener.py
File 
packaging/services/ovirt-fence-kdump-listener/ovirt-fence-kdump-listener.py:

Line 75:         self._config = configfile.ConfigFile(
Line 76:             (
Line 77:                 self._defaults,
Line 78:                 config.ENGINE_VARS,
Line 79:                 config.ENGINE_FKLSNR_VARS,
you should not mix two configurations at one load.

there are defaults for one and defaults for the other, there is file for one 
and file for the other.
Line 80:             ),
Line 81:         )
Line 82: 
Line 83:         self._checkInstallation(


Line 88:         consoleLog = open(os.devnull, "w+")
Line 89:         return (consoleLog, consoleLog)
Line 90: 
Line 91:     def daemonContext(self):
Line 92:         db_manager = db.ConnectionManager(
with ....
Line 93:             host=self._config.get('ENGINE_DB_HOST'),
Line 94:             port=self._config.get('ENGINE_DB_PORT'),
Line 95:             database=self._config.get('ENGINE_DB_DATABASE'),
Line 96:             username=self._config.get('ENGINE_DB_USER'),


Line 95:             database=self._config.get('ENGINE_DB_DATABASE'),
Line 96:             username=self._config.get('ENGINE_DB_USER'),
Line 97:             password=self._config.get('ENGINE_DB_PASSWORD'),
Line 98:             secured=self._config.getboolean('ENGINE_DB_SECURED'),
Line 99:             secure_validation=(
we do:

 secure_validation=self._config.geboolean(
     '......'
 ),

:)
Line 100:                 
self._config.getboolean('ENGINE_DB_SECURED_VALIDATION')
Line 101:             ),
Line 102:         )
Line 103: 


Line 98:             secured=self._config.getboolean('ENGINE_DB_SECURED'),
Line 99:             secure_validation=(
Line 100:                 
self._config.getboolean('ENGINE_DB_SECURED_VALIDATION')
Line 101:             ),
Line 102:         )
) as db_manager:
Line 103: 
Line 104:         with db_manager:
Line 105:             dao = db.EngineDao(connection_manager=db_manager)
Line 106: 


Line 116:                         
config_values['FenceKdumpListenerHeartbeatInterval']
Line 117:                     ),
Line 118:                     session_expiration_time=int(
Line 119:                         config_values['KdumpFinishedTimeout']
Line 120:                     ),
if you load these explicitly in dao, why don't you convert presentation there?
Line 121:             ) as server:
Line 122:                 server.run()
Line 123: 
Line 124: 


-- 
To view, visit http://gerrit.ovirt.org/27201
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: comment
Gerrit-Change-Id: Ieec3bad47bbba860a52a9ff4e2eb7f61277f4e36
Gerrit-PatchSet: 6
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Martin Peřina <mper...@redhat.com>
Gerrit-Reviewer: Alon Bar-Lev <alo...@redhat.com>
Gerrit-Reviewer: Barak Azulay <bazu...@redhat.com>
Gerrit-Reviewer: Eli Mesika <emes...@redhat.com>
Gerrit-Reviewer: Martin Peřina <mper...@redhat.com>
Gerrit-Reviewer: Oved Ourfali <oourf...@redhat.com>
Gerrit-Reviewer: Saggi Mizrahi <smizr...@redhat.com>
Gerrit-Reviewer: automat...@ovirt.org
Gerrit-Reviewer: oVirt Jenkins CI Server
Gerrit-HasComments: Yes
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to