def run_project(self): """Run a project and allocate the necessary resources.""" def start_container(): """Start CernVM fork with the proper context.""" memory_option = "'lxc.cgroup.memory.limit_in_bytes = {0}K'" swap_option = "'lxc.cgroup.memory.memsw.limit_in_bytes = {0}K'" mount_entry_option = "'lxc.mount.entry = {0}'" metafile_option = "'DUMBQ_METAFILE = /{0}'" # Basic command configuration repos_with_commas = ",".join(project_repos) cernvm_fork_command = [ self.cernvm_fork_bin, container_name, "-n", "-d", "-f", "--run={0}".format(container_run), "--cvmfs={0}".format(repos_with_commas), "-o " + memory_option.format(quota_mem), "-o " + swap_option.format(quota_swap) ] # Mount shared mountpoint if mount_options: cernvm_fork_command.append( "-o " + mount_entry_option.format(mount_options)) # Share metadata file if exists if self.shared_meta_file: cernvm_fork_command.append( ("-E " + metafile_option.format(self.guest_meta_file))) # Pass configuration environment variables for envvar in self.envvars: cernvm_fork_command.append( "-E " + "'DUMBQ_{0}'".format(envvar)) cernvm_fork_command.extend([ "-E " + "'DUMBQ_NAME={0}'".format(project_name), "-E " + "'DUMBQ_UUID={0}'".format(container_uuid), "-E " + "'DUMBQ_VMID={0}'".format(self.host_uuid) ]) # Append bind shares for bind_share in bind_shares: cernvm_fork_command.append( "-o " + mount_entry_option.format(bind_share)) # Return if container started correctly start_message = (self.feedback["starting_project"] .format(container_name)) self.logger.info(start_message) return call(cernvm_fork_command, stdout=DEVNULL) == 0 def post_start_project(): """Copy metadata, create runfile, update index and open tty.""" if self.shared_meta_file: path_to_copy = (self.config["guest_mountpoint"] .format(container_name, self.guest_meta_file)) parent_path = re.sub("[^/]+$", "", path_to_copy) os.makedirs(parent_path) shutil.copy(self.shared_meta_file, path_to_copy) project_info = jsonify( uuid=container_uuid, wwwroot="/inst-{0}".format(container_name), project=project_name, memory=quota_mem, swap=quota_swap, cpus=quota_cpu ) flag_filepath = os.path.join(self.run_dir, container_name) safe_write_to_file(flag_filepath, project_info, self.logger.error) if self.www_dir: self.update_project_stats() # Only open tty if the option is enabled if self.base_tty > 0: self.open_tty(container_name) return True # Get project to run, quotas and container conf project = self.pick_project() project_name = project[0] project_repos = project[2].split(",") project_script = project[3] quota_cpu = self.hw_info.slot_cpu quota_mem = self.hw_info.slot_mem quota_swap = self.hw_info.slot_swap + self.hw_info.slot_mem container_uuid = str(uuid4()) container_name = "{0}-{1}".format(project_name, container_uuid) # If testing flag on, use local script if self.testing: container_run = project_script else: container_run = "/cvmfs/{0}".format(project_script) # Mount WWW dir if self.www_dir: mountpoint = "{0}/inst-{1}".format(self.www_dir, container_name) create_dir_if_nonexistent(mountpoint, mode=0555) guest_shared_mount = self.config["guest_shared_mount"] mount_options = ("{0} {1} none defaults,bind,user 0 0" .format(mountpoint, guest_shared_mount)) # Aggregate bind shares with mount options bind_shares = [] for bind_share in self.bind_mount: # Get `host, guest` or `host, host` hg = bind_share.split("=") dir_host = hg[0] hg.append(dir_host) dir_guest = hg[1] rel_path = re.sub("^/?", "", dir_guest) mount_options = ("{0} {1} none defaults,bind 0 0" .format(mountpoint, rel_path)) bind_shares.append(mount_options) # Start container, post_start and log any error if start_container(): is_success = post_start_project() else: cernvm_error = self.feedback["cernvm_error"] self.logger.error(cernvm_error) is_success = False return container_name if is_success else ""
def run_project(self): """Run a project and allocate the necessary resources.""" def start_container(): """Start CernVM fork with the proper context.""" memory_option = "'lxc.cgroup.memory.limit_in_bytes = {0}K'" swap_option = "'lxc.cgroup.memory.memsw.limit_in_bytes = {0}K'" mount_entry_option = "'lxc.mount.entry = {0}'" metafile_option = "'DUMBQ_METAFILE = /{0}'" # Basic command configuration repos_with_commas = ",".join(project_repos) cernvm_fork_command = [ self.cernvm_fork_bin, container_name, "-n", "-d", "-f", "--run={0}".format(container_run), "--cvmfs={0}".format(repos_with_commas), "-o " + memory_option.format(quota_mem), "-o " + swap_option.format(quota_swap) ] # Mount shared mountpoint if mount_options: cernvm_fork_command.append( "-o " + mount_entry_option.format(mount_options)) # Share metadata file if exists if self.shared_meta_file: cernvm_fork_command.append( ("-E " + metafile_option.format(self.guest_meta_file))) # Pass configuration environment variables for envvar in self.envvars: cernvm_fork_command.append("-E " + "'DUMBQ_{0}'".format(envvar)) cernvm_fork_command.extend([ "-E " + "'DUMBQ_NAME={0}'".format(project_name), "-E " + "'DUMBQ_UUID={0}'".format(container_uuid), "-E " + "'DUMBQ_VMID={0}'".format(self.host_uuid) ]) # Append bind shares for bind_share in bind_shares: cernvm_fork_command.append( "-o " + mount_entry_option.format(bind_share)) # Return if container started correctly start_message = ( self.feedback["starting_project"].format(container_name)) self.logger.info(start_message) return call(cernvm_fork_command, stdout=DEVNULL) == 0 def post_start_project(): """Copy metadata, create runfile, update index and open tty.""" if self.shared_meta_file: path_to_copy = (self.config["guest_mountpoint"].format( container_name, self.guest_meta_file)) parent_path = re.sub("[^/]+$", "", path_to_copy) os.makedirs(parent_path) shutil.copy(self.shared_meta_file, path_to_copy) project_info = jsonify(uuid=container_uuid, wwwroot="/inst-{0}".format(container_name), project=project_name, memory=quota_mem, swap=quota_swap, cpus=quota_cpu) flag_filepath = os.path.join(self.run_dir, container_name) safe_write_to_file(flag_filepath, project_info, self.logger.error) if self.www_dir: self.update_project_stats() # Only open tty if the option is enabled if self.base_tty > 0: self.open_tty(container_name) return True # Get project to run, quotas and container conf project = self.pick_project() project_name = project[0] project_repos = project[2].split(",") project_script = project[3] quota_cpu = self.hw_info.slot_cpu quota_mem = self.hw_info.slot_mem quota_swap = self.hw_info.slot_swap + self.hw_info.slot_mem container_uuid = str(uuid4()) container_name = "{0}-{1}".format(project_name, container_uuid) # If testing flag on, use local script if self.testing: container_run = project_script else: container_run = "/cvmfs/{0}".format(project_script) # Mount WWW dir if self.www_dir: mountpoint = "{0}/inst-{1}".format(self.www_dir, container_name) create_dir_if_nonexistent(mountpoint, mode=0555) guest_shared_mount = self.config["guest_shared_mount"] mount_options = ("{0} {1} none defaults,bind,user 0 0".format( mountpoint, guest_shared_mount)) # Aggregate bind shares with mount options bind_shares = [] for bind_share in self.bind_mount: # Get `host, guest` or `host, host` hg = bind_share.split("=") dir_host = hg[0] hg.append(dir_host) dir_guest = hg[1] rel_path = re.sub("^/?", "", dir_guest) mount_options = ("{0} {1} none defaults,bind 0 0".format( mountpoint, rel_path)) bind_shares.append(mount_options) # Start container, post_start and log any error if start_container(): is_success = post_start_project() else: cernvm_error = self.feedback["cernvm_error"] self.logger.error(cernvm_error) is_success = False return container_name if is_success else ""
def setup_public_www(self): """Create public WWW folder and make it readable.""" if self.config["www_dir"]: create_dir_if_nonexistent(self.www_dir, mode=0555)