def createPath(self, alter_user=True): """ Create the directory of the partition, assign to the partition user and give it the 750 permission. In case if path exists just modifies it. """ self.path = os.path.abspath(self.path) owner = self.user if self.user else User('root') if not os.path.exists(self.path): os.mkdir(self.path, 0o750) if alter_user: owner_pw = pwd.getpwnam(owner.name) chownDirectory(self.path, owner_pw.pw_uid, owner_pw.pw_gid) os.chmod(self.path, 0o750)
def processComputerPartition(self, computer_partition): """ Process a Computer Partition, depending on its state """ computer_partition_id = computer_partition.getId() # Sanity checks before processing # Those values should not be None or empty string or any falsy value if not computer_partition_id: raise ValueError('Computer Partition id is empty.') # Check if we defined explicit list of partitions to process. # If so, if current partition not in this list, skip. if len(self.computer_partition_filter_list) > 0 and \ (computer_partition_id not in self.computer_partition_filter_list): return self.logger.debug('Check if %s requires processing...' % computer_partition_id) instance_path = os.path.join(self.instance_root, computer_partition_id) # Try to get partition timestamp (last modification date) timestamp_path = os.path.join( instance_path, COMPUTER_PARTITION_TIMESTAMP_FILENAME ) parameter_dict = computer_partition.getInstanceParameterDict() if 'timestamp' in parameter_dict: timestamp = parameter_dict['timestamp'] else: timestamp = None try: software_url = computer_partition.getSoftwareRelease().getURI() except NotFoundError: # Problem with instance: SR URI not set. # Try to process it anyway, it may need to be deleted. software_url = None try: software_path = os.path.join(self.software_root, md5digest(software_url)) except TypeError: # Problem with instance: SR URI not set. # Try to process it anyway, it may need to be deleted. software_path = None periodicity = self.maximum_periodicity if software_path: periodicity_path = os.path.join(software_path, 'periodicity') if os.path.exists(periodicity_path): try: periodicity = int(open(periodicity_path).read()) except ValueError: os.remove(periodicity_path) self.logger.exception('') # Check if timestamp from server is more recent than local one. # If not: it's not worth processing this partition (nothing has # changed). if (computer_partition_id not in self.computer_partition_filter_list and not self.develop and os.path.exists(timestamp_path)): old_timestamp = open(timestamp_path).read() last_runtime = int(os.path.getmtime(timestamp_path)) if timestamp: try: if periodicity == 0: os.remove(timestamp_path) elif int(timestamp) <= int(old_timestamp): # Check periodicity, i.e if periodicity is one day, partition # should be processed at least every day. if int(time.time()) <= (last_runtime + periodicity) or periodicity < 0: self.logger.debug('Partition already up-to-date, skipping.') return else: # Periodicity forced processing this partition. Removing # the timestamp file in case it fails. os.remove(timestamp_path) except ValueError: os.remove(timestamp_path) self.logger.exception('') # Include Partition Logging log_folder_path = "%s/.slapgrid/log" % instance_path mkdir_p(log_folder_path) partition_file_handler = logging.FileHandler( filename="%s/instance.log" % (log_folder_path) ) stat_info = os.stat(instance_path) chownDirectory("%s/.slapgrid" % instance_path, uid=stat_info.st_uid, gid=stat_info.st_gid) formatter = logging.Formatter( '[%(asctime)s] %(levelname)-8s %(name)s %(message)s') partition_file_handler.setFormatter(formatter) self.logger.addHandler(partition_file_handler) try: self.logger.info('Processing Computer Partition %s.' % computer_partition_id) self.logger.info(' Software URL: %s' % software_url) self.logger.info(' Software path: %s' % software_path) self.logger.info(' Instance path: %s' % instance_path) filter_dict = getattr(computer_partition, '_filter_dict', None) if filter_dict: retention_delay = filter_dict.get('retention_delay', '0') else: retention_delay = '0' local_partition = Partition( software_path=software_path, instance_path=instance_path, supervisord_partition_configuration_path=os.path.join( _getSupervisordConfigurationDirectory(self.instance_root), '%s.conf' % computer_partition_id), supervisord_socket=self.supervisord_socket, computer_partition=computer_partition, computer_id=self.computer_id, partition_id=computer_partition_id, server_url=self.master_url, software_release_url=software_url, certificate_repository_path=self.certificate_repository_path, buildout=self.buildout, logger=self.logger, retention_delay=retention_delay, instance_min_free_space=self.instance_min_free_space, instance_storage_home=self.instance_storage_home, ipv4_global_network=self.ipv4_global_network, ) computer_partition_state = computer_partition.getState() # XXX this line breaks 37 tests # self.logger.info(' Instance type: %s' % computer_partition.getType()) self.logger.info(' Instance status: %s' % computer_partition_state) if computer_partition_state == COMPUTER_PARTITION_STARTED_STATE: local_partition.install() computer_partition.available() local_partition.start() self._checkPromises(computer_partition) computer_partition.started() elif computer_partition_state == COMPUTER_PARTITION_STOPPED_STATE: try: # We want to process the partition, even if stopped, because it should # propagate the state to children if any. local_partition.install() computer_partition.available() finally: # Instance has to be stopped even if buildout/reporting is wrong. local_partition.stop() computer_partition.stopped() elif computer_partition_state == COMPUTER_PARTITION_DESTROYED_STATE: local_partition.stop() try: computer_partition.stopped() except (SystemExit, KeyboardInterrupt): computer_partition.error(traceback.format_exc(), logger=self.logger) raise except Exception: pass else: error_string = "Computer Partition %r has unsupported state: %s" % \ (computer_partition_id, computer_partition_state) computer_partition.error(error_string, logger=self.logger) raise NotImplementedError(error_string) finally: self.logger.removeHandler(partition_file_handler) # If partition has been successfully processed, write timestamp if timestamp: open(timestamp_path, 'w').write(timestamp)
def construct(self, alter_user=True, alter_network=True, create_tap=True): """ Construct the computer object as it is. """ if alter_network and self.address is not None: self.interface.addAddr(self.address, self.netmask) for path in self.instance_root, self.software_root: if not os.path.exists(path): os.makedirs(path, 0o755) else: os.chmod(path, 0o755) # own self.software_root by software user slapsoft = User(self.software_user) slapsoft.path = self.software_root if alter_user: slapsoft.create() slapsoft_pw = pwd.getpwnam(slapsoft.name) chownDirectory(slapsoft.path, slapsoft_pw.pw_uid, slapsoft_pw.pw_gid) os.chmod(self.software_root, 0o755) # Speed hack: # Blindly add all IPs from existing configuration, just to speed up actual # computer configuration later on. # XXX-TODO: only add an address if it doesn't already exist. if self.ipv6_interface: interface_name = self.ipv6_interface else: interface_name = self.interface.name for partition in self.partition_list: try: for address in partition.address_list: try: netmask = netmaskToPrefixIPv6(address['netmask']) except: continue callAndRead(['ip', 'addr', 'add', '%s/%s' % (address['addr'], netmask), 'dev', interface_name]) except ValueError: pass try: for partition_index, partition in enumerate(self.partition_list): # Reconstructing User's partition.path = os.path.join(self.instance_root, partition.reference) partition.user.setPath(partition.path) partition.user.additional_group_list = [slapsoft.name] if alter_user: partition.user.create() # Reconstructing Tap if partition.user and partition.user.isAvailable(): owner = partition.user else: owner = User('root') if alter_network and create_tap: # In case it has to be attached to the TAP network device, only one # is necessary for the interface to assert carrier if self.interface.attach_to_tap and partition_index == 0: partition.tap.createWithOwner(owner, attach_to_tap=True) else: partition.tap.createWithOwner(owner) self.interface.addTap(partition.tap) # Reconstructing partition's directory partition.createPath(alter_user) # Reconstructing partition's address # There should be two addresses on each Computer Partition: # * global IPv6 # * local IPv4, took from slapformat:ipv4_local_network if not partition.address_list: # regenerate partition.address_list.append(self.interface.addIPv4LocalAddress()) partition.address_list.append(self.interface.addAddr()) elif alter_network: # regenerate list of addresses old_partition_address_list = partition.address_list partition.address_list = [] if len(old_partition_address_list) != 2: raise ValueError( 'There should be exactly 2 stored addresses. Got: %r' % (old_partition_address_list,)) if not any(netaddr.valid_ipv6(q['addr']) for q in old_partition_address_list): raise ValueError('Not valid ipv6 addresses loaded') if not any(netaddr.valid_ipv4(q['addr']) for q in old_partition_address_list): raise ValueError('Not valid ipv6 addresses loaded') for address in old_partition_address_list: if netaddr.valid_ipv6(address['addr']): partition.address_list.append(self.interface.addAddr( address['addr'], address['netmask'])) elif netaddr.valid_ipv4(address['addr']): partition.address_list.append(self.interface.addIPv4LocalAddress( address['addr'])) else: raise ValueError('Address %r is incorrect' % address['addr']) finally: if alter_network and create_tap and self.interface.attach_to_tap: try: self.partition_list[0].tap.detach() except IndexError: pass
def _updateFolderOwner(self, folder_path=None): stat_info = os.stat(self.partition_folder) if folder_path is None: folder_path = os.path.join(self.partition_folder, PROMISE_STATE_FOLDER_NAME) chownDirectory(folder_path, stat_info.st_uid, stat_info.st_gid)