[Bf-blender-cvs] [76d50c51a3f] master: Buildbot: Support multiple workers talking to single codesign server

Sergey Sharybin noreply at git.blender.org
Tue Jun 16 14:14:13 CEST 2020


Commit: 76d50c51a3f7c68e8f30f7fbc5dd2731dd06856b
Author: Sergey Sharybin
Date:   Tue Jun 16 14:08:14 2020 +0200
Branches: master
https://developer.blender.org/rB76d50c51a3f7c68e8f30f7fbc5dd2731dd06856b

Buildbot: Support multiple workers talking to single codesign server

Is achieved by replacing hard-coded signed/unsigned file names with
"<uuid>" which acts as a "request ID". This way multiple workers can
put their requests into a single directory without collisions. The
code sign server will handle the requests sequentially in an unknown
order.

===================================================================

M	build_files/buildbot/codesign/base_code_signer.py

===================================================================

diff --git a/build_files/buildbot/codesign/base_code_signer.py b/build_files/buildbot/codesign/base_code_signer.py
index 2f86531a4d0..66953bfc5e5 100644
--- a/build_files/buildbot/codesign/base_code_signer.py
+++ b/build_files/buildbot/codesign/base_code_signer.py
@@ -48,6 +48,7 @@ import shutil
 import subprocess
 import time
 import tarfile
+import uuid
 
 from pathlib import Path
 from tempfile import TemporaryDirectory
@@ -121,21 +122,10 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
     # Consider this an input of the code signing server.
     unsigned_storage_dir: Path
 
-    # Information about archive which contains files which are to be signed.
-    #
-    # This archive is created by the buildbot worked and acts as an input for
-    # the code signing server.
-    unsigned_archive_info: ArchiveWithIndicator
-
     # Storage where signed files are stored.
     # Consider this an output of the code signer server.
     signed_storage_dir: Path
 
-    # Information about archive which contains signed files.
-    #
-    # This archive is created by the code signing server.
-    signed_archive_info: ArchiveWithIndicator
-
     # Platform the code is currently executing on.
     platform: util.Platform
 
@@ -146,50 +136,44 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
 
         # Unsigned (signing server input) configuration.
         self.unsigned_storage_dir = absolute_shared_storage_dir / 'unsigned'
-        self.unsigned_archive_info = ArchiveWithIndicator(
-            self.unsigned_storage_dir, 'unsigned_files.tar', 'ready.stamp')
 
         # Signed (signing server output) configuration.
         self.signed_storage_dir = absolute_shared_storage_dir / 'signed'
-        self.signed_archive_info = ArchiveWithIndicator(
-            self.signed_storage_dir, 'signed_files.tar', 'ready.stamp')
 
         self.platform = util.get_current_platform()
 
-    """
-    General note on cleanup environment functions.
-
-    It is expected that there is only one instance of the code signer server
-    running for a given input/output directory, and that it serves a single
-    buildbot worker.
-    By its nature, a buildbot worker only produces one build at a time and
-    never performs concurrent builds.
-    This leads to a conclusion that when starting in a clean environment
-    there shouldn't be any archives remaining from a previous build.
+    def cleanup_environment_for_builder(self) -> None:
+        # TODO(sergey): Revisit need of cleaning up the existing files.
+        # In practice it wasn't so helpful, and with multiple clients
+        # talking to the same server it becomes even mor etricky.
+        pass
 
-    However, it is possible to have various failure scenarios which might
-    leave the environment in a non-clean state:
+    def cleanup_environment_for_signing_server(self) -> None:
+        # TODO(sergey): Revisit need of cleaning up the existing files.
+        # In practice it wasn't so helpful, and with multiple clients
+        # talking to the same server it becomes even mor etricky.
+        pass
 
-        - Network hiccup which makes buildbot worker to stop current build
-          and re-start it after connection to server is re-established.
+    def generate_request_id(self) -> str:
+        """
+        Generate an unique identifier for code signing request.
+        """
+        return str(uuid.uuid4())
 
-          Note, this could also happen during buildbot server maintenance.
+    def archive_info_for_request_id(
+            self, path: Path, request_id: str) -> ArchiveWithIndicator:
+        return ArchiveWithIndicator(
+            path, f'{request_id}.tar', f'{request_id}.ready')
 
-        - Signing server might get restarted due to updates or other reasons.
+    def signed_archive_info_for_request_id(
+            self, request_id: str) -> ArchiveWithIndicator:
+        return self.archive_info_for_request_id(
+            self.signed_storage_dir, request_id);
 
-    Requiring manual interaction in such cases is not something good to
-    require, so here we simply assume that the system is used the way it is
-    intended to and restore environment to a prestine clean state.
-    """
-
-    def cleanup_environment_for_builder(self) -> None:
-        self.unsigned_archive_info.clean()
-        self.signed_archive_info.clean()
-
-    def cleanup_environment_for_signing_server(self) -> None:
-        # Don't clear the requested to-be-signed archive since we might be
-        # restarting signing machine while the buildbot is busy.
-        self.signed_archive_info.clean()
+    def unsigned_archive_info_for_request_id(
+            self, request_id: str) -> ArchiveWithIndicator:
+        return self.archive_info_for_request_id(
+            self.unsigned_storage_dir, request_id);
 
     ############################################################################
     # Buildbot worker side helpers.
@@ -232,7 +216,7 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
                               if self.check_file_is_to_be_signed(file)]
         return files_to_be_signed
 
-    def wait_for_signed_archive_or_die(self) -> None:
+    def wait_for_signed_archive_or_die(self, request_id) -> None:
         """
         Wait until archive with signed files is available.
 
@@ -240,13 +224,19 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
         is still no responce from the signing server the application will exit
         with a non-zero exit code.
         """
+
+        signed_archive_info = self.signed_archive_info_for_request_id(
+            request_id)
+        unsigned_archive_info = self.unsigned_archive_info_for_request_id(
+            request_id)
+
         timeout_in_seconds = self.config.TIMEOUT_IN_SECONDS
         time_start = time.monotonic()
-        while not self.signed_archive_info.is_ready():
+        while not signed_archive_info.is_ready():
             time.sleep(1)
             time_slept_in_seconds = time.monotonic() - time_start
             if time_slept_in_seconds > timeout_in_seconds:
-                self.unsigned_archive_info.clean()
+                unsigned_archive_info.clean()
                 raise SystemExit("Signing server didn't finish signing in "
                                  f"{timeout_in_seconds} seconds, dying :(")
 
@@ -303,13 +293,19 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
             return
         logger_builder.info('Found %d files to sign.', len(files))
 
+        request_id = self.generate_request_id()
+        signed_archive_info = self.signed_archive_info_for_request_id(
+            request_id)
+        unsigned_archive_info = self.unsigned_archive_info_for_request_id(
+            request_id)
+
         pack_files(files=files,
-                   archive_filepath=self.unsigned_archive_info.archive_filepath)
-        self.unsigned_archive_info.tag_ready()
+                   archive_filepath=unsigned_archive_info.archive_filepath)
+        unsigned_archive_info.tag_ready()
 
         # Wait for the signing server to finish signing.
         logger_builder.info('Waiting signing server to sign the files...')
-        self.wait_for_signed_archive_or_die()
+        self.wait_for_signed_archive_or_die(request_id)
 
         # Extract signed files from archive and move files to final location.
         with TemporaryDirectory(prefix='blender-buildbot-') as temp_dir_str:
@@ -317,7 +313,7 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
 
             logger_builder.info('Extracting signed files from archive...')
             extract_files(
-                archive_filepath=self.signed_archive_info.archive_filepath,
+                archive_filepath=signed_archive_info.archive_filepath,
                 extraction_dir=unpacked_signed_files_dir)
 
             destination_dir = path
@@ -327,19 +323,39 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
                 unpacked_signed_files_dir, destination_dir)
 
         logger_builder.info('Removing archive with signed files...')
-        self.signed_archive_info.clean()
+        signed_archive_info.clean()
 
     ############################################################################
     # Signing server side helpers.
 
-    def wait_for_sign_request(self) -> None:
+    def wait_for_sign_request(self) -> str:
         """
         Wait for the buildbot to request signing of an archive.
+
+        Returns an identifier of signing request.
         """
+
         # TOOD(sergey): Support graceful shutdown on Ctrl-C.
-        while not self.unsigned_archive_info.is_ready():
+
+        logger_server.info(
+            'Waiting for a READY indicator of any signign request.')
+        request_id = None
+        while request_id is None:
+            for file in self.unsigned_storage_dir.iterdir():
+                if file.suffix != '.ready':
+                    continue
+                request_id = file.stem
+                logger_server.info(f'Found READY for request ID {request_id}.')
+            if request_id is None:
+                time.sleep(1)
+
+        unsigned_archive_info = self.unsigned_archive_info_for_request_id(
+            request_id)
+        while not unsigned_archive_info.is_ready():
             time.sleep(1)
 
+        return request_id
+
     @abc.abstractmethod
     def sign_all_files(self, files: List[AbsoluteAndRelativeFileName]) -> None:
         """
@@ -348,7 +364,7 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
         NOTE: Signing should happen in-place.
         """
 
-    def run_signing_pipeline(self):
+    def run_signing_pipeline(self, request_id: str):
         """
         Run the full signing pipeline starting from the point when buildbot
         worker have requested signing.
@@ -360,9 +376,14 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
         with TemporaryDirectory(prefix='blender-codesign-') as temp_dir_str:
             temp_dir = Path(temp_dir_str)
 
+            signed_archive_info = self.signed_archive_info_for_request_id(
+                request_id)
+            unsigned_archive_info = self.unsigned_archive_info_for_request_id(
+                request_id)
+
             logger_server.info('Extracting unsigned files from archive...')
   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list