Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: client/run_isolated.py

Issue 2847153002: Cache/retrieve extracted CIPD packages in local isolate cache (Closed)
Patch Set: clean up formatting Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2012 The LUCI Authors. All rights reserved. 2 # Copyright 2012 The LUCI Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 3 # Use of this source code is governed under the Apache License, Version 2.0
4 # that can be found in the LICENSE file. 4 # that can be found in the LICENSE file.
5 5
6 """Runs a command with optional isolated input/output. 6 """Runs a command with optional isolated input/output.
7 7
8 Despite name "run_isolated", can run a generic non-isolated command specified as 8 Despite name "run_isolated", can run a generic non-isolated command specified as
9 args. 9 args.
10 10
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 RUN_ISOLATED_LOG_FILE = 'run_isolated.log' 86 RUN_ISOLATED_LOG_FILE = 'run_isolated.log'
87 87
88 88
89 # The name of the log to use for the run_test_cases.py command 89 # The name of the log to use for the run_test_cases.py command
90 RUN_TEST_CASES_LOG = 'run_test_cases.log' 90 RUN_TEST_CASES_LOG = 'run_test_cases.log'
91 91
92 92
93 # Use short names for temporary directories. This is driven by Windows, which 93 # Use short names for temporary directories. This is driven by Windows, which
94 # imposes a relatively short maximum path length of 260 characters, often 94 # imposes a relatively short maximum path length of 260 characters, often
95 # referred to as MAX_PATH. It is relatively easy to create files with longer 95 # referred to as MAX_PATH. It is relatively easy to create files with longer
96 # path length. A use case is with recursive depedency treesV like npm packages. 96 # path length. A use case is with recursive dependency trees like npm packages.
97 # 97 #
98 # It is recommended to start the script with a `root_dir` as short as 98 # It is recommended to start the script with a `root_dir` as short as
99 # possible. 99 # possible.
100 # - ir stands for isolated_run 100 # - ir stands for isolated_run
101 # - io stands for isolated_out 101 # - io stands for isolated_out
102 # - it stands for isolated_tmp 102 # - it stands for isolated_tmp
103 ISOLATED_RUN_DIR = u'ir' 103 ISOLATED_RUN_DIR = u'ir'
104 ISOLATED_OUT_DIR = u'io' 104 ISOLATED_OUT_DIR = u'io'
105 ISOLATED_TMP_DIR = u'it' 105 ISOLATED_TMP_DIR = u'it'
106 106
107 107
108 def get_as_zip_package(executable=True): 108 def get_as_zip_package(executable=True):
109 """Returns ZipPackage with this module and all its dependencies. 109 """Returns ZipPackage with this module and all its dependencies.
110 110
111 If |executable| is True will store run_isolated.py as __main__.py so that 111 If |executable| is True will store run_isolated.py as __main__.py so that
112 zip package is directly executable be python. 112 zip package is directly executable be python.
113 """ 113 """
114 # Building a zip package when running from another zip package is 114 # Building a zip package when running from another zip package is
115 # unsupported and probably unneeded. 115 # unsupported and probably unneeded.
116 assert not zip_package.is_zipped_module(sys.modules[__name__]) 116 assert not zip_package.is_zipped_module(sys.modules[__name__])
117 assert THIS_FILE_PATH 117 assert THIS_FILE_PATH
118 assert BASE_DIR 118 assert BASE_DIR
119 package = zip_package.ZipPackage(root=BASE_DIR) 119 package = zip_package.ZipPackage(root=BASE_DIR)
120 package.add_python_file(THIS_FILE_PATH, '__main__.py' if executable else None) 120 package.add_python_file(THIS_FILE_PATH, '__main__.py' if executable else None)
121 package.add_python_file(os.path.join(BASE_DIR, 'isolate_storage.py')) 121 package.add_python_file(os.path.join(BASE_DIR, 'isolate_storage.py'))
122 package.add_python_file(os.path.join(BASE_DIR, 'isolated_format.py')) 122 package.add_python_file(os.path.join(BASE_DIR, 'isolated_format.py'))
123 package.add_python_file(os.path.join(BASE_DIR, 'isolateserver.py')) 123 package.add_python_file(os.path.join(BASE_DIR, 'isolateserver.py'))
124 package.add_python_file(os.path.join(BASE_DIR, 'isolate_format.py'))
124 package.add_python_file(os.path.join(BASE_DIR, 'auth.py')) 125 package.add_python_file(os.path.join(BASE_DIR, 'auth.py'))
125 package.add_python_file(os.path.join(BASE_DIR, 'cipd.py')) 126 package.add_python_file(os.path.join(BASE_DIR, 'cipd.py'))
126 package.add_python_file(os.path.join(BASE_DIR, 'named_cache.py')) 127 package.add_python_file(os.path.join(BASE_DIR, 'named_cache.py'))
128 package.add_python_file(os.path.join(BASE_DIR, 'run_isolated.py'))
127 package.add_directory(os.path.join(BASE_DIR, 'libs')) 129 package.add_directory(os.path.join(BASE_DIR, 'libs'))
128 package.add_directory(os.path.join(BASE_DIR, 'third_party')) 130 package.add_directory(os.path.join(BASE_DIR, 'third_party'))
129 package.add_directory(os.path.join(BASE_DIR, 'utils')) 131 package.add_directory(os.path.join(BASE_DIR, 'utils'))
130 return package 132 return package
131 133
132 134
133 def make_temp_dir(prefix, root_dir): 135 def make_temp_dir(prefix, root_dir):
134 """Returns a new unique temporary directory.""" 136 """Returns a new unique temporary directory."""
135 return unicode(tempfile.mkdtemp(prefix=prefix, dir=root_dir)) 137 return unicode(tempfile.mkdtemp(prefix=prefix, dir=root_dir))
136 138
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 'pins', # dict with installed cipd pins to return to the server 681 'pins', # dict with installed cipd pins to return to the server
680 ]) 682 ])
681 683
682 684
683 @contextlib.contextmanager 685 @contextlib.contextmanager
684 def noop_install_packages(_run_dir): 686 def noop_install_packages(_run_dir):
685 """Placeholder for 'install_client_and_packages' if cipd is disabled.""" 687 """Placeholder for 'install_client_and_packages' if cipd is disabled."""
686 yield None 688 yield None
687 689
688 690
689 def _install_packages(run_dir, cipd_cache_dir, client, packages, timeout): 691 def _install_packages(run_dir, cipd_cache_dir, client, packages, timeout,
692 isolate_cache=None):
690 """Calls 'cipd ensure' for packages. 693 """Calls 'cipd ensure' for packages.
691 694
692 Args: 695 Args:
693 run_dir (str): root of installation. 696 run_dir (str): root of installation.
694 cipd_cache_dir (str): the directory to use for the cipd package cache. 697 cipd_cache_dir (str): the directory to use for the cipd package cache.
695 client (CipdClient): the cipd client to use 698 client (CipdClient): the cipd client to use
696 packages: packages to install, list [(path, package_name, version), ...]. 699 packages: packages to install, list [(path, package_name, version), ...].
697 timeout: max duration in seconds that this function can take. 700 timeout: max duration in seconds that this function can take.
698 701
699 Returns: list of pinned packages. Looks like [ 702 Returns: list of pinned packages. Looks like [
(...skipping 22 matching lines...) Expand all
722 by_path[path].append((name, version, i)) 725 by_path[path].append((name, version, i))
723 726
724 pins = client.ensure( 727 pins = client.ensure(
725 run_dir, 728 run_dir,
726 { 729 {
727 subdir: [(name, vers) for name, vers, _ in pkgs] 730 subdir: [(name, vers) for name, vers, _ in pkgs]
728 for subdir, pkgs in by_path.iteritems() 731 for subdir, pkgs in by_path.iteritems()
729 }, 732 },
730 cache_dir=cipd_cache_dir, 733 cache_dir=cipd_cache_dir,
731 timeout=timeout, 734 timeout=timeout,
735 isolate_cache=isolate_cache,
732 ) 736 )
733 737
734 for subdir, pin_list in sorted(pins.iteritems()): 738 for subdir, pin_list in sorted(pins.iteritems()):
735 this_subdir = by_path[subdir] 739 this_subdir = by_path[subdir]
736 for i, (name, version) in enumerate(pin_list): 740 for i, (name, version) in enumerate(pin_list):
737 insert_pin(subdir, name, version, this_subdir[i][2]) 741 insert_pin(subdir, name, version, this_subdir[i][2])
738 742
739 assert None not in package_pins 743 assert None not in package_pins
740 744
741 return package_pins 745 return package_pins
742 746
743 747
744 @contextlib.contextmanager 748 @contextlib.contextmanager
745 def install_client_and_packages( 749 def install_client_and_packages(
746 run_dir, packages, service_url, client_package_name, 750 run_dir, packages, service_url, client_package_name,
747 client_version, cache_dir, timeout=None): 751 client_version, cache_dir, timeout=None, isolate_cache=None):
748 """Bootstraps CIPD client and installs CIPD packages. 752 """Bootstraps CIPD client and installs CIPD packages.
749 753
750 Yields CipdClient, stats, client info and pins (as single CipdInfo object). 754 Yields CipdClient, stats, client info and pins (as single CipdInfo object).
751 755
752 Pins and the CIPD client info are in the form of: 756 Pins and the CIPD client info are in the form of:
753 [ 757 [
754 { 758 {
755 "path": path, "package_name": package_name, "version": version, 759 "path": path, "package_name": package_name, "version": version,
756 }, 760 },
757 ... 761 ...
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 client_manager = cipd.get_client( 796 client_manager = cipd.get_client(
793 service_url, client_package_name, client_version, cache_dir, 797 service_url, client_package_name, client_version, cache_dir,
794 timeout=timeoutfn()) 798 timeout=timeoutfn())
795 799
796 with client_manager as client: 800 with client_manager as client:
797 get_client_duration = time.time() - get_client_start 801 get_client_duration = time.time() - get_client_start
798 802
799 package_pins = [] 803 package_pins = []
800 if packages: 804 if packages:
801 package_pins = _install_packages( 805 package_pins = _install_packages(
802 run_dir, cipd_cache_dir, client, packages, timeoutfn()) 806 run_dir, cipd_cache_dir, client, packages, timeoutfn(), isolate_cache)
803 807
804 file_path.make_tree_files_read_only(run_dir) 808 file_path.make_tree_files_read_only(run_dir)
805 809
806 total_duration = time.time() - start 810 total_duration = time.time() - start
807 logging.info( 811 logging.info(
808 'Installing CIPD client and packages took %d seconds', total_duration) 812 'Installing CIPD client and packages took %d seconds', total_duration)
809 813
810 yield CipdInfo( 814 yield CipdInfo(
811 client=client, 815 client=client,
812 cache_dir=cipd_cache_dir, 816 cache_dir=cipd_cache_dir,
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 if options.json: 1002 if options.json:
999 options.json = unicode(os.path.abspath(options.json)) 1003 options.json = unicode(os.path.abspath(options.json))
1000 1004
1001 cipd.validate_cipd_options(parser, options) 1005 cipd.validate_cipd_options(parser, options)
1002 1006
1003 install_packages_fn = noop_install_packages 1007 install_packages_fn = noop_install_packages
1004 if options.cipd_enabled: 1008 if options.cipd_enabled:
1005 install_packages_fn = lambda run_dir: install_client_and_packages( 1009 install_packages_fn = lambda run_dir: install_client_and_packages(
1006 run_dir, cipd.parse_package_args(options.cipd_packages), 1010 run_dir, cipd.parse_package_args(options.cipd_packages),
1007 options.cipd_server, options.cipd_client_package, 1011 options.cipd_server, options.cipd_client_package,
1008 options.cipd_client_version, cache_dir=options.cipd_cache) 1012 options.cipd_client_version, cache_dir=options.cipd_cache,
1013 isolate_cache=isolate_cache)
1009 1014
1010 @contextlib.contextmanager 1015 @contextlib.contextmanager
1011 def init_named_caches(run_dir): 1016 def init_named_caches(run_dir):
1012 # WARNING: this function depends on "options" variable defined in the outer 1017 # WARNING: this function depends on "options" variable defined in the outer
1013 # function. 1018 # function.
1014 with named_cache_manager.open(): 1019 with named_cache_manager.open():
1015 named_cache_manager.create_symlinks(run_dir, options.named_caches) 1020 named_cache_manager.create_symlinks(run_dir, options.named_caches)
1016 try: 1021 try:
1017 yield 1022 yield
1018 finally: 1023 finally:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 return 1 1065 return 1
1061 1066
1062 1067
1063 if __name__ == '__main__': 1068 if __name__ == '__main__':
1064 subprocess42.inhibit_os_error_reporting() 1069 subprocess42.inhibit_os_error_reporting()
1065 # Ensure that we are always running with the correct encoding. 1070 # Ensure that we are always running with the correct encoding.
1066 fix_encoding.fix_encoding() 1071 fix_encoding.fix_encoding()
1067 file_path.enable_symlink() 1072 file_path.enable_symlink()
1068 1073
1069 sys.exit(main(sys.argv[1:])) 1074 sys.exit(main(sys.argv[1:]))
OLDNEW
« client/cipd.py ('K') | « client/isolateserver.py ('k') | client/utils/fs.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698