@@ -507,11 +507,20 @@ class NodeOutcome:
507507 *error_code* / *error_msg* go into the node's ``data`` and are set only
508508 on an infrastructure failure (result == "incomplete"), matching the
509509 kernelci-pipeline scheduler convention.
510+
511+ *artifacts* is merged into the node's existing ``artifacts`` dict on
512+ finish. kernelci-pipeline's send_kcidb keys on ``artifacts.test_log``
513+ (or ``lava_log``) when emitting the maestro-origin KCIDB row's
514+ ``log_url`` — see kernelci-pipeline/src/send_kcidb.py:579-582 and
515+ ``_get_artifacts`` (send_kcidb.py:443-455), which walks the parent
516+ chain, so a value written on the job node is visible to every test
517+ descendant.
510518 """
511519
512520 result : str
513521 error_code : Optional [str ] = None
514522 error_msg : Optional [str ] = None
523+ artifacts : Optional [Dict [str , str ]] = None
515524
516525
517526# ---------------------------------------------------------------------------
@@ -793,6 +802,13 @@ def _finish_node(self, node_id: str, outcome: NodeOutcome) -> bool:
793802 data ["error_code" ] = outcome .error_code
794803 data ["error_msg" ] = outcome .error_msg
795804 current ["data" ] = data
805+ if outcome .artifacts :
806+ # Merge (don't replace) so we never blow away artifacts a
807+ # previous step put on the node — e.g. job_definition, which
808+ # event polling reads via node.artifacts.job_definition.
809+ artifacts = current .get ("artifacts" ) or {}
810+ artifacts .update (outcome .artifacts )
811+ current ["artifacts" ] = artifacts
796812 payload = {k : v for k , v in current .items () if k not in NODE_READ_ONLY_FIELDS }
797813 try :
798814 _http_put_json (url , payload , token = self .api_token )
@@ -954,21 +970,62 @@ def _execute_job(
954970 ]
955971
956972 # error_code + "incomplete" only on an infrastructure failure; a job
957- # that actually ran is pass/fail/skip from its tests. Independent of
958- # whether the KCIDB submission below succeeds.
973+ # that actually ran is pass/fail/skip from its tests.
959974 outcome = infra_error or NodeOutcome (_node_result_from_rows (test_rows ))
960- try :
961- submit_tests (
962- self .kcidb_submit_url ,
963- self .kcidb_jwt ,
964- self .kcidb_origin ,
965- build_id ,
966- test_rows ,
975+
976+ # --- KCIDB direct submission DISABLED -----------------------------
977+ # We used to POST these test_rows to KCIDB ourselves under origin
978+ # `pull_labs_aws_ec2`. That produced a parallel row keyed
979+ # (pull_labs_aws_ec2, <node_id>.<instance_id>) which KCIDB stored
980+ # but the dashboard never displayed, because the dashboard looks up
981+ # the maestro-origin row (origin=maestro, id=maestro:<node_id>)
982+ # emitted by kernelci-pipeline's send_kcidb. Net effect: our log_url
983+ # landed in KCIDB but was invisible (see archive submissions
984+ # uIuuMb... vs. l6CD9xy... — same node, two origins, only ours had
985+ # the URL).
986+ #
987+ # New flow: write the boot log URL onto the maestro node's artifacts
988+ # below; send_kcidb picks it up via artifacts.test_log (which it
989+ # walks the parent chain for, send_kcidb.py:443-455) and emits the
990+ # single, dashboard-visible row.
991+ #
992+ # The row-building code above is kept intentionally so the outcome
993+ # derivation (_node_result_from_rows) keeps working and so we can
994+ # re-enable dual submission cheaply if the maestro path regresses.
995+ #
996+ # try:
997+ # submit_tests(
998+ # self.kcidb_submit_url,
999+ # self.kcidb_jwt,
1000+ # self.kcidb_origin,
1001+ # build_id,
1002+ # test_rows,
1003+ # )
1004+ # except urllib.error.URLError as e:
1005+ # logger.error("KCIDB submit failed for node %s: %s", node_id, e)
1006+ # return False, outcome
1007+ # ------------------------------------------------------------------
1008+
1009+ # Collect per-instance log URLs to write back onto the maestro node.
1010+ # send_kcidb only consumes the canonical `test_log` key (or
1011+ # `lava_log`, which isn't ours), so use that for the first URL;
1012+ # extra URLs from multi-VM jobs are preserved under suffixed keys
1013+ # so they aren't lost — they just won't show up as `log_url` on
1014+ # KCIDB until we move to per-instance child nodes.
1015+ log_urls = [r ["log_url" ] for r in test_rows if r .get ("log_url" )]
1016+ if log_urls :
1017+ outcome .artifacts = {"test_log" : log_urls [0 ]}
1018+ for i , url in enumerate (log_urls [1 :], start = 1 ):
1019+ outcome .artifacts [f"test_log_{ i } " ] = url
1020+ logger .info (
1021+ "Attaching %d log URL(s) to node %s artifacts (test_log=%s)" ,
1022+ len (log_urls ), node_id , log_urls [0 ],
1023+ )
1024+ else :
1025+ logger .info (
1026+ "No log URLs to attach for node %s (test_rows=%d)" ,
1027+ node_id , len (test_rows ),
9671028 )
968- except urllib .error .URLError as e :
969- logger .error ("KCIDB submit failed for node %s: %s" , node_id , e )
970- return False , outcome
971- logger .info ("Submitted %d test row(s) for node %s" , len (test_rows ), node_id )
9721029 return True , outcome
9731030
9741031 # -- Loop -----------------------------------------------------------
0 commit comments