def test_load_from_cache_caches_each_file_separately(self): log1, log2 = self.make_file(), self.make_file() config1 = self.make_file(contents=yaml.safe_dump({'logfile': log1})) config2 = self.make_file(contents=yaml.safe_dump({'logfile': log2})) self.assertEqual(log1, Config.load_from_cache(config1)['logfile']) self.assertEqual(log2, Config.load_from_cache(config2)['logfile'])
def test_load_from_cache_reloads_from_cache_not_from_file(self): # A config loaded by Config.load_from_cache() is never reloaded. filename = self.make_file(name="config.yaml", contents='') config_before = Config.load_from_cache(filename) os.unlink(filename) config_after = Config.load_from_cache(filename) self.assertEqual(config_before, config_after)
def test_load_from_cache_caches_immutable_copy(self): logfile = self.make_file() filename = self.make_file( name="config.yaml", contents=yaml.safe_dump({'logfile': logfile})) first_load = Config.load_from_cache(filename) second_load = Config.load_from_cache(filename) self.assertEqual(first_load, second_load) self.assertIsNot(first_load, second_load) first_load['logfile'] = factory.make_name('otherlog') self.assertNotEqual(first_load['logfile'], second_load['logfile']) self.assertEqual(logfile, second_load['logfile']) self.assertIsNot(first_load['boot'], second_load['boot']) first_load['boot']['architectures'] = [factory.make_name('otherarch')] self.assertNotEqual( first_load['boot']['architectures'], second_load['boot']['architectures'])
def get_bcd_load_options(self, params): client = self.clients[params['remote']] data = client['data'] loadoptions = '%s;%s;%s' % \ (Config.load_from_cache()['windows']['remote_path'], "%s\\source" % data['release'], data['preseed_url'].replace('/', '\\')) return (loadoptions, params)
def test_does_not_modify_config(self): self.useFixture(ConfigFixture({ 'boot': { 'architectures': [factory.make_name('arch')], 'ephemeral': { 'images_directory': self.make_dir(), 'releases': [factory.make_name('release')], }, }, })) original_boot_config = deepcopy(Config.load_from_cache()['boot']) install_legacy_config(self, make_legacy_config()) make_arg_parser(factory.getRandomString()) self.assertEqual( original_boot_config, Config.load_from_cache()['boot'])
def test_does_not_modify_config(self): self.useFixture( ConfigFixture({ 'boot': { 'architectures': [factory.make_name('arch')], 'ephemeral': { 'images_directory': self.make_dir(), 'releases': [factory.make_name('release')], }, }, })) original_boot_config = deepcopy(Config.load_from_cache()['boot']) install_legacy_config(self, make_legacy_config()) make_arg_parser(factory.getRandomString()) self.assertEqual(original_boot_config, Config.load_from_cache()['boot'])
def report_to_server(): """For master worker only: report available netboot images.""" maas_url, api_credentials = get_cached_knowledge() if not all([maas_url, api_credentials]): return images = tftppath.list_boot_images( Config.load_from_cache()['tftp']['root']) submit(maas_url, api_credentials, images)
def make_arg_parser(doc): """Create an `argparse.ArgumentParser` for this script. :param doc: Description of the script, for help output. """ try: config = Config.load_from_cache() except IOError as e: if e.errno != errno.ENOENT: raise # Plod on with defaults. There may be a legacy shell-script config. config = Config.get_defaults() # Merge legacy settings into our copy of the config. merge_legacy_ephemerals_config(config) filters = [] arches = config['boot'].get('architectures') if arches is not None: filters.append(compose_filter('arch', arches)) releases = config['boot']['ephemeral'].get('releases') if releases is not None: filters.append(compose_filter('release', releases)) images_directory = config['boot']['ephemeral'].get('images_directory') parser = ArgumentParser(description=doc) parser.add_argument( '--path', action="store", default="streams/v1/index.sjson", help="Path to simplestreams index file, relative to mirror URL") parser.add_argument( '--url', action='store', default=RELEASES_URL, help="Simplestreams mirror URL (may use 'file://' for local mirror)") parser.add_argument( '--output', action='store', default=images_directory, help="Directory where boot images should be stored") parser.add_argument( '--max', action='store', default=1, help="Store downloads for only the MAX most recent images.") parser.add_argument( '--keyring', action='store', default=DEFAULT_KEYRING, help="gpg keyring for verifying boot image metadata") parser.add_argument( '--delete', action='store_true', default=False, help="Delete local copies of images when no longer available") parser.add_argument( '--products', action='store', default=PRODUCTS_REGEX, help="Regular expression matching products to import, " "e.g. com.ubuntu.maas.daily:ephemerals:.* for daily") parser.add_argument( 'filters', nargs='*', default=filters, help="Simplestreams filters for image metadata to download, " "e.g. arch=i386 release=precise") return parser
def get_ephemeral_name(release, arch): """Return the name of the most recent ephemeral image. That information is read from the config file named 'info' in the ephemeral directory e.g: /var/lib/maas/ephemeral/precise/ephemeral/i386/20120424/info """ config = Config.load_from_cache() root = os.path.join(config["boot"]["ephemeral"]["images_directory"], release, 'ephemeral', arch) try: filename = os.path.join(get_last_directory(root), 'info') except OSError: raise EphemeralImagesDirectoryNotFound( "The directory containing the ephemeral images/info is missing " "(%r). Make sure to run the script " "'maas-import-pxe-files'." % root) name = parse_key_value_file(filename, separator="=")['name'] return name
def get_ephemeral_name(release, arch): """Return the name of the most recent ephemeral image. That information is read from the config file named 'info' in the ephemeral directory e.g: /var/lib/maas/ephemeral/precise/ephemeral/i386/20120424/info """ config = Config.load_from_cache() root = os.path.join( config["boot"]["ephemeral"]["images_directory"], release, 'ephemeral', arch) try: filename = os.path.join(get_last_directory(root), 'info') except OSError: raise EphemeralImagesDirectoryNotFound( "The directory containing the ephemeral images/info is missing " "(%r). Make sure to run the script " "'maas-import-pxe-files'." % root) name = parse_key_value_file(filename, separator="=")['name'] return name
def install_image(image_dir, arch, subarch, release, purpose, config_file=None, alternate_purpose=None): """Install a PXE boot image. This is the function-call equivalent to a command-line invocation calling `add_arguments` and `run`. """ config = Config.load_from_cache(config_file) tftproot = config["tftp"]["root"] destination = make_destination(tftproot, arch, subarch, release, purpose) if not are_identical_dirs(destination, image_dir): # Image has changed. Move the new version into place. install_dir(image_dir, destination) if alternate_purpose is not None: # Symlink the new image directory under the alternate purpose name. alternate_destination = make_destination( tftproot, arch, subarch, release, alternate_purpose) install_symlink(destination, alternate_destination) rmtree(image_dir, ignore_errors=True)
def return_binary_path(data): r = params['remote'] self.clients[r] = {} self.clients[r]['data'] = data self.clients[r]['is_windows'] = False log.msg(">>>>>NODE DETAILS%r" % data) release = data.get('release') if data.get('purpose') == 'local': raise FileNotFound("pxelinux.0") if release.startswith('win'): self.clients[r]['is_windows'] = True path = "pxeboot.0" self.base = FilePath( '/var/lib/maas/tftp/%s/%s/%s/install/' % (data['arch'], data['subarch'], data['release'])) self.clients[r]['base'] = self.base else: self.is_windows = False self.base = FilePath(Config.load_from_cache()['tftp']['root']) self.clients[r]['base'] = self.base path = "pxelinux.0" return path.encode('utf-8')
def test_load_from_cache_uses_defaults(self): filename = self.make_file(name='config.yaml', contents='') self.assertEqual( Config.get_defaults(), Config.load_from_cache(filename))
def test_load_from_cache_loads_config(self): logfile = self.make_file() filename = self.make_file( name="config.yaml", contents=yaml.safe_dump({'logfile': logfile})) loaded_config = Config.load_from_cache(filename) self.assertEqual(logfile, loaded_config['logfile'])