def imagingServerImageDelete(self, imageUUID): """ Delete an image (backup or master) from the imaging server. The corresponding directory is simply removed. @param imageUUID: image UUID @type: str @return: True if it worked, else False @rtype: bool """ if not isUUID(imageUUID): self.logger.warn("Bad image UUID %s" % str(imageUUID)) ret = False else: path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) if os.path.exists(path): try: shutil.rmtree(path) ret = True except Exception, e: self.logger.error( "Error while removing image with UUID %s: %s" % (imageUUID, e)) ret = False else:
def computerUnregister(self, computerUUID, imageList, archive): """ Unregister a computer from the imaging service: - move its boot menu into the archive directory - move its home directory into the archive directory - move its backup images into the archive directory All this move are done in background in another thread, so that it is not blocking the whole package server. @rtype: bool @return: True if the operation succeeded to start """ assert (type(imageList) == list) if not isUUID(computerUUID): return False macAddress = self.myUUIDCache.getByUUID(computerUUID) if not macAddress: return False else: macAddress = macAddress['mac'] archiver = Archiver(self.config, archive, computerUUID, macAddress, imageList) ret = archiver.check() and archiver.prepare() if ret: # If all is OK, start archival process in another thread archiver.run() return ret
def imagingServerImageDelete(self, imageUUID): """ Delete an image (backup or master) from the imaging server. The corresponding directory is simply removed. @param imageUUID: image UUID @type: str @return: True if it worked, else False @rtype: bool """ if not isUUID(imageUUID): self.logger.warn("Bad image UUID %s" % str(imageUUID)) ret = False else: path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) if os.path.exists(path): try: shutil.rmtree(path) ret = True except Exception, e: self.logger.error("Error while removing image with UUID %s: %s" % (imageUUID, e)) ret = False else:
def computerUnregister(self, computerUUID, imageList, archive): """ Unregister a computer from the imaging service: - move its boot menu into the archive directory - move its home directory into the archive directory - move its backup images into the archive directory All this move are done in background in another thread, so that it is not blocking the whole package server. @rtype: bool @return: True if the operation succeeded to start """ assert(type(imageList) == list) if not isUUID(computerUUID): return False macAddress = self.myUUIDCache.getByUUID(computerUUID) if not macAddress: return False else: macAddress = macAddress['mac'] archiver = Archiver(self.config, archive, computerUUID, macAddress, imageList) ret = archiver.check() and archiver.prepare() if ret: # If all is OK, start archival process in another thread archiver.run() return ret
def imageGetLogs(self, imageUUID): """ Send the backup logs of an image. The content of the log.txt file of the image folder is returned. @param imageUUID: image UUID from which logs are wanted @type imageUUID: str @rtype: list @return: list of str with the image logs, or an empty list on error """ ret = [] if not isUUID(imageUUID): self.logger.error('Bad image UUID %s' % str(imageUUID)) else: path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) try: image = Pulse2Image(path, False) ret = image.logs except Exception, e: self.logger.error( "Can't get backup logs of image with UUID %s: %s" % (imageUUID, str(e)))
def test_06computerCreateImageDirectory(self): """ Create a directory to store a Pulse 2 image """ result = SERVER.computerCreateImageDirectory('00:11:22:33:44:ff') self.assertTrue(isUUID(result)) self.assertTrue(os.path.exists('/var/lib/pulse2/imaging/masters/%s' % result)) global IMAGE_UUID IMAGE_UUID = result
def test_06computerCreateImageDirectory(self): """ Create a directory to store a Pulse 2 image """ result = SERVER.computerCreateImageDirectory('00:11:22:33:44:ff') self.assertTrue(isUUID(result)) self.assertTrue( os.path.exists('/var/lib/pulse2/imaging/masters/%s' % result)) global IMAGE_UUID IMAGE_UUID = result
def computersMenuSet(self, menus): """ Set computers imaging boot menu. @param menus: list of (uuid, menu) couples @type menus: list @ret: list of the computer uuid which menu have been successfully set @rtype: list """ ret = [] for cuuid in menus: menu = menus[cuuid] if not isUUID(cuuid): self.logger.error('Invalid computer UUID %s' % cuuid) continue if not isMenuStructure(menu): self.logger.error( "Invalid menu structure for computer UUID %s" % cuuid) continue res = self.myUUIDCache.getByUUID(cuuid) if res == False: self.logger.warn("Updating MAC address for UUID %s" % cuuid) self.myUUIDCache.set( menu['target']['uuid'], menu['target']['macaddress'], menu['target']['name'], '') # FIXME : domainname '' is probably a wrong idea res = self.myUUIDCache.getByUUID(cuuid) try: macaddress = res['mac'] hostname = res['shortname'] self.logger.debug( 'Setting menu for computer UUID/MAC/hostname %s/%s/%s' % (cuuid, macaddress, hostname)) imb = ImagingComputerMenuBuilder(self.config, macaddress, menu) imenu = imb.make() imenu.write() ret.append(cuuid) imc = ImagingComputerConfiguration(self.config, cuuid, hostname, menu) imc.write() except Exception, e: self.logger.exception( "Error while setting new menu of computer uuid/mac %s: %s" % (cuuid, e))
def imageGetLogs(self, imageUUID): """ Send the backup logs of an image. The content of the log.txt file of the image folder is returned. @param imageUUID: image UUID from which logs are wanted @type imageUUID: str @rtype: list @return: list of str with the image logs, or an empty list on error """ ret = [] if not isUUID(imageUUID): self.logger.error('Bad image UUID %s' % str(imageUUID)) else: path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) try: image = Pulse2Image(path, False) ret = image.logs except Exception, e: self.logger.error("Can't get backup logs of image with UUID %s: %s" % (imageUUID, str(e)))
def computersMenuSet(self, menus): """ Set computers imaging boot menu. @param menus: list of (uuid, menu) couples @type menus: list @ret: list of the computer uuid which menu have been successfully set @rtype: list """ ret = [] for cuuid in menus: menu = menus[cuuid] if not isUUID(cuuid): self.logger.error('Invalid computer UUID %s' % cuuid) continue if not isMenuStructure(menu): self.logger.error("Invalid menu structure for computer UUID %s" % cuuid) continue res = self.myUUIDCache.getByUUID(cuuid) if res == False: self.logger.warn("Updating MAC address for UUID %s" % cuuid) self.myUUIDCache.set(menu['target']['uuid'], menu['target']['macaddress'], menu['target']['name'], '') # FIXME : domainname '' is probably a wrong idea res = self.myUUIDCache.getByUUID(cuuid) try: macaddress = res['mac'] hostname = res['shortname'] self.logger.debug('Setting menu for computer UUID/MAC/hostname %s/%s/%s' % (cuuid, macaddress, hostname)) imb = ImagingComputerMenuBuilder(self.config, macaddress, menu) imenu = imb.make() imenu.write() ret.append(cuuid) imc = ImagingComputerConfiguration(self.config, cuuid, hostname, menu) imc.write() except Exception, e: self.logger.exception("Error while setting new menu of computer uuid/mac %s: %s" % (cuuid, e))
def imageDone(self, computerMACAddress, imageUUID): """ Called by the imaging server to register a new image. @return: True if successful @rtype: bool """ def _onSuccess(result): if type(result) != list and len(result) != 2: self.logger.error( 'Imaging: Couldn\'t update on the MMC agent the image with UUID %s : %s' % (imageUUID, str(result))) ret = False elif not result[0]: self.logger.error( 'Imaging: Couldn\'t update on the MMC agent the image with UUID %s : %s' % (imageUUID, result[1])) ret = False else: image_path = os.path.join( self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) shortname = self.getClientShortname(computerMACAddress) if shortname: self.logger.info( 'Imaging: Disk image of client %s (%s) created successfully into %s' % (shortname, computerMACAddress, image_path)) else: self.logger.info( 'Imaging: Disk image of unknown client (%s) created successfully into %s' % (computerMACAddress, image_path)) ret = True return ret def _gotMAC(result): """ Process result return by getComputerByMac, BTW should be either False or the required info """ if not result: self.logger.error( "Can't get computer UUID for MAC address %s" % (computerMACAddress)) return False else: # start gathering details about our image path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) image = Pulse2Image(path) if not image: state = "INVALID" size = 0 # FIXME : use actual size name = "Failed backup of %s" % result['shortname'] desc = "%s, %s" % (rfc3339Time(), humanReadable(size)) elif image.has_error: state = "FAILED" size = image.size name = "Backup of %s" % result['shortname'] desc = "%s, %s" % (rfc3339Time(), humanReadable(size)) else: state = "DONE" size = image.size name = "Backup of %s" % result['shortname'] desc = "%s, %s" % (rfc3339Time(), humanReadable(size)) c_uuid = result['uuid'] updateDate = tuple(gmtime()) client = self._getXMLRPCClient() func = 'imaging.imageUpdate' # size converted to float to bypass xmlrpc limitations args = (self.config.imaging_api['uuid'], c_uuid, imageUUID, name, desc, float(size), updateDate, state) d = client.callRemote(func, *args) d.addCallbacks(_onSuccess, RPCReplay().onError, errbackArgs=(func, args, False)) return True if not isUUID(imageUUID): self.logger.error("Bad image UUID %s" % str(imageUUID)) ret = False elif not isMACAddress(computerMACAddress): self.logger.error("Bad computer MAC %s" % str(computerMACAddress)) ret = False else: d = self.getComputerByMac(computerMACAddress) d.addCallback(_gotMAC) return d return ret
def imageDone(self, computerMACAddress, imageUUID): """ Called by the imaging server to register a new image. @return: True if successful @rtype: bool """ def _onSuccess(result): if type(result) != list and len(result) != 2: self.logger.error('Imaging: Couldn\'t update on the MMC agent the image with UUID %s : %s' % (imageUUID, str(result))) ret = False elif not result[0]: self.logger.error('Imaging: Couldn\'t update on the MMC agent the image with UUID %s : %s' % (imageUUID, result[1])) ret = False else: image_path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) shortname = self.getClientShortname(computerMACAddress) if shortname: self.logger.info('Imaging: Disk image of client %s (%s) created successfully into %s' % (shortname, computerMACAddress, image_path)) else: self.logger.info('Imaging: Disk image of unknown client (%s) created successfully into %s' % (computerMACAddress, image_path)) ret = True return ret def _gotMAC(result): """ Process result return by getComputerByMac, BTW should be either False or the required info """ if not result: self.logger.error("Can't get computer UUID for MAC address %s" % (computerMACAddress)) return False else: # start gathering details about our image path = os.path.join(self.config.imaging_api['base_folder'], self.config.imaging_api['masters_folder'], imageUUID) image = Pulse2Image(path) if not image: state = "INVALID" size = 0 # FIXME : use actual size name = "Failed backup of %s" % result['shortname'] desc = "%s, %s" % (rfc3339Time(), humanReadable(size)) elif image.has_error : state = "FAILED" size = image.size name = "Backup of %s" % result['shortname'] desc = "%s, %s" % (rfc3339Time(), humanReadable(size)) else : state = "DONE" size = image.size name = "Backup of %s" % result['shortname'] desc = "%s, %s" % (rfc3339Time(), humanReadable(size)) c_uuid = result['uuid'] updateDate = tuple(gmtime()) client = self._getXMLRPCClient() func = 'imaging.imageUpdate' # size converted to float to bypass xmlrpc limitations args = (self.config.imaging_api['uuid'], c_uuid, imageUUID, name, desc, float(size), updateDate, state) d = client.callRemote(func, *args) d.addCallbacks(_onSuccess, RPCReplay().onError, errbackArgs = (func, args, False)) return True if not isUUID(imageUUID): self.logger.error("Bad image UUID %s" % str(imageUUID)) ret = False elif not isMACAddress(computerMACAddress): self.logger.error("Bad computer MAC %s" % str(computerMACAddress)) ret = False else: d = self.getComputerByMac(computerMACAddress) d.addCallback(_gotMAC) return d return ret
def test_UUIDNotValid(self): self.assertFalse(isUUID('UUID0')) self.assertFalse(isUUID('UUID-10')) self.assertFalse(isUUID('')) self.assertFalse(isUUID('1a10b1f4-bb6e-4798-b39e-bb8d090dd8b')) self.assertFalse(isUUID(42))
def setup(self, config_file): self.config_file = config_file if self.cp == None: # Load configuration file if sys.platform != "win32": self.cp = Pulse2ConfigParser() else: self.cp = ConfigParser.ConfigParser() self.cp.read(config_file) self.cp.read(config_file + '.local') if self.cp.has_option("main", "bind"): # TODO remove in a future version logging.getLogger().warning( "'bind' is obsolete, please replace it in your config file by 'host'" ) self.bind = self.cp.get("main", 'bind') elif self.cp.has_option('main', 'host'): self.bind = self.cp.get("main", 'host') if self.cp.has_option('main', 'port'): self.port = self.cp.getint("main", 'port') if self.cp.has_option('main', 'public_ip'): self.public_ip = self.cp.get("main", 'public_ip') else: self.public_ip = self.bind if sys.platform != "win32": if self.cp.has_section('daemon'): if self.cp.has_option('daemon', 'pidfile'): self.pid_path = self.cp.get('daemon', 'pidfile') if self.cp.has_option("daemon", "user"): self.daemon_user = pwd.getpwnam( self.cp.get("daemon", "user"))[2] if self.cp.has_option("daemon", "group"): self.daemon_group = grp.getgrnam( self.cp.get("daemon", "group"))[2] if self.cp.has_option("daemon", "umask"): self.umask = int(self.cp.get("daemon", "umask"), 8) if sys.platform == "win32": if self.cp.has_option("main", "use_iocp_reactor"): self.use_iocp_reactor = self.cp.getboolean( "main", "use_iocp_reactor") if self.cp.has_option('ssl', 'username'): self.username = self.cp.get('ssl', 'username') if sys.platform != "win32": self.password = self.cp.getpassword('ssl', 'password') else: self.password = self.cp.get('ssl', 'password') if not isTwistedEnoughForLoginPass(): if self.username: logging.getLogger().warn( "your version of twisted is not high enough to use login (ssl/username)" ) self.username = '' if self.password != '': logging.getLogger().warning( "your version of twisted is not high enough to use password (ssl/password)" ) self.password = '' if self.cp.has_option('ssl', 'enablessl'): self.enablessl = self.cp.getboolean('ssl', 'enablessl') if self.enablessl: self.proto = 'https' if self.cp.has_option('ssl', 'certfile'): self.cacert = self.cp.get('ssl', 'certfile') if self.cp.has_option('ssl', 'cacert'): self.cacert = self.cp.get('ssl', 'cacert') if self.cp.has_option('ssl', 'privkey'): self.localcert = self.cp.get('ssl', 'privkey') if self.cp.has_option('ssl', 'localcert'): self.localcert = self.cp.get('ssl', 'localcert') if self.cp.has_option('ssl', 'verifypeer'): self.verifypeer = self.cp.getboolean('ssl', 'verifypeer') if not os.path.isfile(self.localcert): raise Exception('can\'t read SSL key "%s"' % (self.localcert)) return False if not os.path.isfile(self.cacert): raise Exception('can\'t read SSL certificate "%s"' % (self.cacert)) return False if self.verifypeer: # we need twisted.internet.ssl.Certificate to activate certs import twisted.internet.ssl if not hasattr(twisted.internet.ssl, "Certificate"): raise Exception( 'I need at least Python Twisted 2.5 to handle peer checking' ) return False if self.cp.has_section('mirror_api'): self.mirror_api['mount_point'] = '/rpc' if self.cp.has_option('mirror_api', 'mount_point'): self.mirror_api['mount_point'] = self.cp.get( 'mirror_api', 'mount_point') if self.cp.has_section('user_packageapi_api'): self.user_package_api['mount_point'] = '/upaa' if self.cp.has_option('user_packageapi_api', 'mount_point'): self.user_package_api['mount_point'] = self.cp.get( 'user_packageapi_api', 'mount_point') if self.cp.has_section('scheduler_api'): self.scheduler_api['mount_point'] = '/scheduler_api' self.scheduler_api['schedulers'] = 'scheduler_01' if self.cp.has_option('scheduler_api', 'mount_point'): self.scheduler_api['mount_point'] = self.cp.get( 'scheduler_api', 'mount_point') if self.cp.has_option('scheduler_api', 'schedulers'): self.scheduler_api['schedulers'] = self.cp.get( 'scheduler_api', 'schedulers') if self.cp.has_option('main', 'tmp_input_dir'): self.tmp_input_dir = self.cp.get('main', 'tmp_input_dir') for section in self.cp.sections(): if re.compile('^mirror:[0-9]+$').match(section): mount_point = self.cp.get(section, 'mount_point') src = self.cp.get(section, 'src') mirror = {'mount_point': mount_point, 'src': src} if self.cp.has_option(section, 'mirror'): mirror['mirror'] = self.cp.get(section, 'mirror') self.mirrors.append(mirror) if re.compile('^package_api_get:[0-9]+$').match(section): mount_point = self.cp.get(section, 'mount_point') src = self.cp.get(section, 'src') self.package_api_get.append({ 'mount_point': mount_point, 'src': src }) if re.compile('^package_api_put:[0-9]+$').match(section): mount_point = self.cp.get(section, 'mount_point') src = self.cp.get(section, 'src') pap_tmp_input_dir = self.tmp_input_dir if self.cp.has_option(section, 'tmp_input_dir'): self.package_detect_activate = True self.package_detect_tmp_activate = True pap_tmp_input_dir = self.cp.get(section, 'tmp_input_dir') self.package_api_put.append({ 'mount_point': mount_point, 'src': src, 'tmp_input_dir': pap_tmp_input_dir }) # [mmc_agent] section parsing self.mmc_agent = {} if self.cp.has_section("mmc_agent"): self.mmc_agent = { 'host': "127.0.0.1", 'port': 7080, 'username': '******', 'password': '******', 'enablessl': True, 'verifypeer': False, 'cacert': mmcconfdir + "/pulse2/package-server/keys/cacert.pem", 'localcert': mmcconfdir + "/pulse2/package-server/keys/privkey.pem" } if self.cp.has_option('mmc_agent', 'host'): self.mmc_agent['host'] = self.cp.get('mmc_agent', 'host') if self.cp.has_option('mmc_agent', 'port'): self.mmc_agent['port'] = self.cp.getint('mmc_agent', 'port') if self.cp.has_option('mmc_agent', 'enablessl'): self.mmc_agent['enablessl'] = self.cp.getboolean( 'mmc_agent', 'enablessl') if self.cp.has_option('mmc_agent', 'verifypeer'): self.mmc_agent['verifypeer'] = self.cp.getboolean( 'mmc_agent', 'verifypeer') if self.cp.has_option('mmc_agent', 'cacert'): self.mmc_agent['cacert'] = self.cp.get('mmc_agent', 'cacert') if self.cp.has_option('mmc_agent', 'localcert'): self.mmc_agent['localcert'] = self.cp.get( 'mmc_agent', 'localcert') if self.mmc_agent['enablessl']: if not os.path.isfile(self.mmc_agent['localcert']): raise Exception('can\'t read SSL key "%s"' % (self.mmc_agent['localcert'])) return False if not os.path.isfile(self.mmc_agent['cacert']): raise Exception('can\'t read SSL certificate "%s"' % (self.mmc_agent['cacert'])) return False if self.mmc_agent[ 'verifypeer']: # we need twisted.internet.ssl.Certificate to activate certs import twisted.internet.ssl if not hasattr(twisted.internet.ssl, "Certificate"): raise Exception( 'I need at least Python Twisted 2.5 to handle peer checking' ) return False # [imaging_api] section parsing if self.cp.has_section("imaging_api") and self.cp.has_option( "imaging_api", 'uuid'): # mount point imaging_mp = '/imaging_api' # base folder base_folder = '/var/lib/pulse2/imaging' # will contain the bootloader material (revoboot + splashscreen), served by tftp bootloader_folder = 'bootloader' # CDROM bootloader cdrom_bootloader = 'cdrom_boot' # Boot splash screen bootsplash_file = 'bootsplash.xpm' # will contain the boot menus, served by tftp bootmenus_folder = 'bootmenus' # will contain diskless stuff (kernel, initramfs, additional tools), served by tftp diskless_folder = 'diskless' # diskless kernel diskless_kernel = 'kernel' # diskless initrd diskless_initrd = 'initrd' # diskless initrd for CD-ROM diskless_initrdcd = 'initrdcd' # diskless memtest tool diskless_memtest = 'memtest' # diskless dban tool diskless_dban = 'dban' # will contain computer-related materials computers_folder = 'computers' # will contain inventories inventories_folder = 'inventories' # will contain masters, served by tftp masters_folder = 'masters' # will contain postinstall binaries postinst_folder = 'postinst' # will contain archived computer imaging data archives_folder = 'archives' # will contain generated ISO images isos_folder = '/var/lib/pulse2/imaging/isos' # tool used to generate ISO file isogen_tool = '/usr/bin/genisoimage' # will contain our UUID/MAC Addr cache uuid_cache_file = os.path.join(base_folder, 'uuid-cache.txt') # our UUID/MAC Addr cache lifetime uuid_cache_lifetime = 300 # RPC replay file rpc_replay_file = os.path.join(base_folder, 'rpc-replay.pck') # RPC replay loop timer in seconds rpc_loop_timer = 60 # RPC to replay at each loop rpc_count = 10 # Interval in seconds between two RPCs rpc_interval = 2 # Package Server UUID uuid = "" # listening on this port to communicate with PXE pxe_port = 1001 # inventory host inventory_host = "127.0.0.1" # inventory port inventory_port = 9999 # inventory SSL enable inventory_enablessl = False # on glpi, PXE register by minimal inventory glpi_mode = False # identification on PXE console if self.cp.has_option("imaging_api", 'mount_point'): imaging_mp = self.cp.get("imaging_api", 'mount_point') if self.cp.has_option('imaging_api', 'base_folder'): base_folder = self.cp.get('imaging_api', 'base_folder') if self.cp.has_option('imaging_api', 'bootloader_folder'): bootloader_folder = self.cp.get('imaging_api', 'bootloader_folder') if self.cp.has_option('imaging_api', 'cdrom_bootloader'): cdrom_bootloader = self.cp.get('imaging_api', 'cdrom_bootloader') if self.cp.has_option('imaging_api', 'bootsplash_file'): bootsplash_file = self.cp.get('imaging_api', 'bootlsplash_file') if self.cp.has_option('imaging_api', 'bootmenus_folder'): bootmenus_folder = self.cp.get('imaging_api', 'bootmenus_folder') if self.cp.has_option('imaging_api', 'diskless_folder'): diskless_folder = self.cp.get('imaging_api', 'diskless_folder') if self.cp.has_option("imaging_api", 'diskless_kernel'): diskless_kernel = self.cp.get("imaging_api", 'diskless_kernel') if self.cp.has_option("imaging_api", 'diskless_initrd'): diskless_initrd = self.cp.get("imaging_api", 'diskless_initrd') if self.cp.has_option('imaging_api', 'diskless_initrdcd'): diskless_initrdcd = self.cp.get("imaging_api", 'diskless_initrdcd') if self.cp.has_option("imaging_api", 'diskless_memtest'): diskless_memtest = self.cp.get("imaging_api", 'diskless_memtest') if self.cp.has_option("imaging_api", 'diskless_dban'): diskless_dban = self.cp.get("imaging_api", 'diskless_dban') if self.cp.has_option('imaging_api', 'computers_folder'): computers_folder = self.cp.get('imaging_api', 'computers_folder') if self.cp.has_option('imaging_api', 'inventories_folder'): inventories_folder = self.cp.get('imaging_api', 'inventories_folder') if self.cp.has_option('imaging_api', 'masters_folder'): masters_folder = self.cp.get('imaging_api', 'masters_folder') if self.cp.has_option('imaging_api', 'postinst_folder'): postinst_folder = self.cp.get('imaging_api', 'postinst_folder') if self.cp.has_option('imaging_api', 'archives_folder'): archives_folder = self.cp.get('imaging_api', 'archives_folder') if self.cp.has_option('imaging_api', 'isos_folder'): isos_folder = self.cp.get('imaging_api', 'isos_folder') if self.cp.has_option('imaging_api', 'isogen_tool'): isogen_tool = self.cp.get('imaging_api', 'isogen_tool') if self.cp.has_option('imaging_api', 'uuid_cache_file'): uuid_cache_file = os.path.join( base_folder, self.cp.get('imaging_api', 'uuid_cache_file')) if self.cp.has_option('imaging_api', 'uuid_cache_lifetime'): uuid_cache_lifetime = self.cp.getint('imaging_api', 'uuid_cache_lifetime') if self.cp.has_option('imaging_api', 'rpc_replay_file'): rpc_replay_file = os.path.join( base_folder, self.cp.get('imaging_api', 'rpc_replay_file')) if self.cp.has_option('imaging_api', 'rpc_loop_timer'): rpc_loop_timer = self.cp.getint('imaging_api', 'rpc_loop_timer') if self.cp.has_option('imaging_api', 'rpc_count'): rpc_count = self.cp.getint('imaging_api', 'rpc_count') if self.cp.has_option('imaging_api', 'rpc_interval'): rpc_interval = self.cp.getint('imaging_api', 'rpc_interval') if self.cp.has_option("imaging_api", 'uuid'): uuid = self.cp.get("imaging_api", 'uuid') if self.cp.has_option("imaging_api", 'glpi_mode'): glpi_mode = self.cp.get("imaging_api", 'glpi_mode') if self.cp.has_option("imaging_api", 'pxe_port'): pxe_port = self.cp.get("imaging_api", 'pxe_port') if self.cp.has_option("imaging_api", 'inventory_host'): inventory_host = self.cp.get("imaging_api", 'inventory_host') if self.cp.has_option("imaging_api", 'inventory_port'): inventory_port = self.cp.get("imaging_api", 'inventory_port') if self.cp.has_option("imaging_api", 'inventory_enablessl'): inventory_enablessl = self.cp.get("imaging_api", 'inventory_enablessl') if not isUUID(uuid): raise TypeError( "'%s' is not an valid UUID : in my config file, section [imaging_api], set a correct uuid." % uuid) self.imaging_api = { 'mount_point': imaging_mp, 'base_folder': base_folder, 'bootloader_folder': bootloader_folder, 'bootsplash_file': bootsplash_file, 'bootmenus_folder': bootmenus_folder, 'cdrom_bootloader': cdrom_bootloader, 'diskless_folder': diskless_folder, 'diskless_kernel': diskless_kernel, 'diskless_initrd': diskless_initrd, 'diskless_initrdcd': diskless_initrdcd, 'diskless_memtest': diskless_memtest, 'diskless_dban': diskless_dban, 'computers_folder': computers_folder, 'inventories_folder': inventories_folder, 'masters_folder': masters_folder, 'postinst_folder': postinst_folder, 'archives_folder': archives_folder, 'isos_folder': isos_folder, 'isogen_tool': isogen_tool, 'pxe_port': pxe_port, 'inventory_host': inventory_host, 'inventory_port': inventory_port, 'inventory_enablessl': inventory_enablessl, 'glpi_mode': glpi_mode, 'uuid': uuid, 'uuid_cache_file': uuid_cache_file, 'uuid_cache_lifetime': uuid_cache_lifetime, 'rpc_replay_file': rpc_replay_file, 'rpc_loop_timer': rpc_loop_timer, 'rpc_count': rpc_count, 'rpc_interval': rpc_interval } if self.cp.has_option("main", "package_detect_activate"): # WARN this must overide the previously defined activate if it is in the config file self.package_detect_activate = self.cp.getboolean( "main", "package_detect_activate") if self.package_detect_activate and self.cp.has_option( "main", "package_detect_loop"): self.package_detect_loop = self.cp.getint( "main", "package_detect_loop") if self.cp.has_option("main", "package_detect_smart_method"): package_detect_smart_method = self.cp.get( "main", "package_detect_smart_method") if package_detect_smart_method != 'none': package_detect_smart_method = package_detect_smart_method.split( ',') self.package_detect_smart = True if 'last_time_modification' in package_detect_smart_method: self.package_detect_smart_method.append( self.SMART_DETECT_LAST) if 'check_in_loop' in package_detect_smart_method: self.package_detect_smart_method.append( self.SMART_DETECT_LOOP) if 'check_size' in package_detect_smart_method: self.package_detect_smart_method.append( self.SMART_DETECT_SIZE) else: logging.getLogger().info( "dont know the package_detect_smart_method '%s'") if self.cp.has_option("main", "package_detect_smart_time"): self.package_detect_smart_time = self.cp.getint( "main", "package_detect_smart_time") else: self.package_detect_smart = False if self.cp.has_option("main", "package_mirror_target"): self.package_mirror_target = self.cp.get( "main", "package_mirror_target").split(' ') if (type(self.package_mirror_target) == str and self.package_mirror_target != '') or \ (type(self.package_mirror_target) == list and len(self.package_mirror_target) == 1 and self.package_mirror_target[0] != '') or \ (type(self.package_mirror_target) == list and len(self.package_mirror_target) != 1): self.package_mirror_activate = True if self.cp.has_option("main", 'package_mirror_status_file'): self.package_mirror_status_file = self.cp.get( "main", 'package_mirror_status_file') if self.cp.has_option("main", 'package_mirror_loop'): self.package_mirror_loop = self.cp.getint( "main", 'package_mirror_loop') if self.cp.has_option("main", 'package_mirror_command'): self.package_mirror_command = self.cp.get( "main", 'package_mirror_command') if self.cp.has_option("main", 'package_mirror_command_options'): self.package_mirror_command_options = self.cp.get( "main", 'package_mirror_command_options').split(' ') if self.cp.has_option( "main", "package_mirror_command_options_ssh_options"): self.package_mirror_command_options_ssh_options = self.cp.get( "main", 'package_mirror_command_options_ssh_options').split( ' ') if self.cp.has_option("main", 'package_mirror_level0_command_options'): self.package_mirror_level0_command_options = self.cp.get( "main", 'package_mirror_level0_command_options').split(' ') if self.cp.has_option("main", "package_global_mirror_activate"): self.package_global_mirror_activate = self.cp.getboolean( "main", "package_global_mirror_activate") if self.cp.has_option("main", "package_global_mirror_loop"): self.package_global_mirror_loop = self.cp.getint( "main", "package_global_mirror_loop") if self.cp.has_option("main", "package_global_mirror_command_options"): self.package_global_mirror_command_options = self.cp.get( "main", "package_global_mirror_command_options").split(' ') if self.cp.has_option("main", "real_package_deletion"): self.real_package_deletion = self.cp.getboolean( "main", "real_package_deletion") if self.cp.has_option("main", "mm_assign_algo"): self.mm_assign_algo = self.cp.get("main", 'mm_assign_algo') if self.cp.has_option("main", "up_assign_algo"): self.up_assign_algo = self.cp.get("main", 'up_assign_algo')
def test_UUIDValid(self): self.assertTrue(isUUID('UUID1')) self.assertTrue(isUUID(u'UUID1')) self.assertTrue(isUUID('1a10b1f4-bb6e-4798-b39e-bb8d090dd8b6'))
def setup(self, config_file): if self.cp == None: # Load configuration file if sys.platform != "win32": self.cp = Pulse2ConfigParser() else: self.cp = ConfigParser.ConfigParser() self.cp.read(config_file) if self.cp.has_option("main", "bind"): # TODO remove in a future version logging.getLogger().warning("'bind' is obsolete, please replace it in your config file by 'host'") self.bind = self.cp.get("main", 'bind') elif self.cp.has_option('main', 'host'): self.bind = self.cp.get("main", 'host') if self.cp.has_option('main', 'port'): self.port = self.cp.getint("main", 'port') if self.cp.has_option('main', 'public_ip'): self.public_ip = self.cp.get("main", 'public_ip') else: self.public_ip = self.bind if sys.platform != "win32": if self.cp.has_section('daemon'): if self.cp.has_option('daemon', 'pidfile'): self.pid_path = self.cp.get('daemon', 'pidfile') if self.cp.has_option("daemon", "user"): self.daemon_user = pwd.getpwnam(self.cp.get("daemon", "user"))[2] if self.cp.has_option("daemon", "group"): self.daemon_group = grp.getgrnam(self.cp.get("daemon", "group"))[2] if self.cp.has_option("daemon", "umask"): self.umask = int(self.cp.get("daemon", "umask"), 8) if sys.platform == "win32": if self.cp.has_option("main", "use_iocp_reactor"): self.use_iocp_reactor = self.cp.getboolean("main", "use_iocp_reactor") if self.cp.has_option('ssl', 'username'): self.username = self.cp.get('ssl', 'username') if sys.platform != "win32": self.password = self.cp.getpassword('ssl', 'password') else: self.password = self.cp.get('ssl', 'password') if not isTwistedEnoughForLoginPass(): if self.username: logging.getLogger().warn("your version of twisted is not high enough to use login (ssl/username)") self.username = '' if self.password != '': logging.getLogger().warning("your version of twisted is not high enough to use password (ssl/password)") self.password = '' if self.cp.has_option('ssl', 'enablessl'): self.enablessl = self.cp.getboolean('ssl', 'enablessl') if self.enablessl: self.proto = 'https' if self.cp.has_option('ssl', 'certfile'): self.cacert = self.cp.get('ssl', 'certfile') if self.cp.has_option('ssl', 'cacert'): self.cacert = self.cp.get('ssl', 'cacert') if self.cp.has_option('ssl', 'privkey'): self.localcert = self.cp.get('ssl', 'privkey') if self.cp.has_option('ssl', 'localcert'): self.localcert = self.cp.get('ssl', 'localcert') if self.cp.has_option('ssl', 'verifypeer'): self.verifypeer = self.cp.getboolean('ssl', 'verifypeer') if not os.path.isfile(self.localcert): raise Exception('can\'t read SSL key "%s"' % (self.localcert)) return False if not os.path.isfile(self.cacert): raise Exception('can\'t read SSL certificate "%s"' % (self.cacert)) return False if self.verifypeer: # we need twisted.internet.ssl.Certificate to activate certs import twisted.internet.ssl if not hasattr(twisted.internet.ssl, "Certificate"): raise Exception('I need at least Python Twisted 2.5 to handle peer checking') return False if self.cp.has_section('mirror_api'): self.mirror_api['mount_point'] = '/rpc' if self.cp.has_option('mirror_api', 'mount_point'): self.mirror_api['mount_point'] = self.cp.get('mirror_api', 'mount_point') if self.cp.has_section('user_packageapi_api'): self.user_package_api['mount_point'] = '/upaa' if self.cp.has_option('user_packageapi_api', 'mount_point'): self.user_package_api['mount_point'] = self.cp.get('user_packageapi_api', 'mount_point') if self.cp.has_section('scheduler_api'): self.scheduler_api['mount_point'] = '/scheduler_api' self.scheduler_api['schedulers'] = 'scheduler_01' if self.cp.has_option('scheduler_api', 'mount_point'): self.scheduler_api['mount_point'] = self.cp.get('scheduler_api', 'mount_point') if self.cp.has_option('scheduler_api', 'schedulers'): self.scheduler_api['schedulers'] = self.cp.get('scheduler_api', 'schedulers') if self.cp.has_option('main', 'tmp_input_dir'): self.tmp_input_dir = self.cp.get('main', 'tmp_input_dir') for section in self.cp.sections(): if re.compile('^mirror:[0-9]+$').match(section): mount_point = self.cp.get(section, 'mount_point') src = self.cp.get(section, 'src') mirror = {'mount_point': mount_point, 'src': src} if self.cp.has_option(section, 'mirror'): mirror['mirror'] = self.cp.get(section, 'mirror') self.mirrors.append(mirror) if re.compile('^package_api_get:[0-9]+$').match(section): mount_point = self.cp.get(section, 'mount_point') src = self.cp.get(section, 'src') self.package_api_get.append({'mount_point': mount_point, 'src': src}) if re.compile('^package_api_put:[0-9]+$').match(section): mount_point = self.cp.get(section, 'mount_point') src = self.cp.get(section, 'src') pap_tmp_input_dir = self.tmp_input_dir if self.cp.has_option(section, 'tmp_input_dir'): self.package_detect_activate = True self.package_detect_tmp_activate = True pap_tmp_input_dir = self.cp.get(section, 'tmp_input_dir') self.package_api_put.append({'mount_point': mount_point, 'src': src, 'tmp_input_dir': pap_tmp_input_dir}) # [mmc_agent] section parsing self.mmc_agent = {} if self.cp.has_section("mmc_agent"): self.mmc_agent = { 'host' : "127.0.0.1", 'port' : 7080, 'username' : 'mmc', 'password' : 's3cr3t', 'enablessl' : True, 'verifypeer' : False, 'cacert' : mmcconfdir + "/pulse2/package-server/keys/cacert.pem", 'localcert' : mmcconfdir + "/pulse2/package-server/keys/privkey.pem"} if self.cp.has_option('mmc_agent', 'host'): self.mmc_agent['host'] = self.cp.get('mmc_agent', 'host') if self.cp.has_option('mmc_agent', 'port'): self.mmc_agent['port'] = self.cp.getint('mmc_agent', 'port') if self.cp.has_option('mmc_agent', 'enablessl'): self.mmc_agent['enablessl'] = self.cp.getboolean('mmc_agent', 'enablessl') if self.cp.has_option('mmc_agent', 'verifypeer'): self.mmc_agent['verifypeer'] = self.cp.getboolean('mmc_agent', 'verifypeer') if self.cp.has_option('mmc_agent', 'cacert'): self.mmc_agent['cacert'] = self.cp.get('mmc_agent', 'cacert') if self.cp.has_option('mmc_agent', 'localcert'): self.mmc_agent['localcert'] = self.cp.get('mmc_agent', 'localcert') if self.mmc_agent['enablessl']: if not os.path.isfile(self.mmc_agent['localcert']): raise Exception('can\'t read SSL key "%s"' % (self.mmc_agent['localcert'])) return False if not os.path.isfile(self.mmc_agent['cacert']): raise Exception('can\'t read SSL certificate "%s"' % (self.mmc_agent['cacert'])) return False if self.mmc_agent['verifypeer']: # we need twisted.internet.ssl.Certificate to activate certs import twisted.internet.ssl if not hasattr(twisted.internet.ssl, "Certificate"): raise Exception('I need at least Python Twisted 2.5 to handle peer checking') return False # [imaging_api] section parsing if self.cp.has_section("imaging_api") and self.cp.has_option("imaging_api", 'uuid'): # mount point imaging_mp = '/imaging_api' # base folder base_folder = '/var/lib/pulse2/imaging' # will contain the bootloader material (revoboot + splashscreen), served by tftp bootloader_folder = 'bootloader' # CDROM bootloader cdrom_bootloader = 'cdrom_boot' # Boot splash screen bootsplash_file = 'bootsplash.xpm' # will contain the boot menus, served by tftp bootmenus_folder = 'bootmenus' # will contain diskless stuff (kernel, initramfs, additional tools), served by tftp diskless_folder = 'diskless' # diskless kernel diskless_kernel = 'kernel' # diskless initrd diskless_initrd = 'initrd' # diskless initrd for CD-ROM diskless_initrdcd = 'initrdcd' # diskless memtest tool diskless_memtest = 'memtest' # will contain computer-related materials computers_folder = 'computers' # will contain inventories inventories_folder = 'inventories' # will contain masters, served by tftp masters_folder = 'masters' # will contain postinstall binaries postinst_folder = 'postinst' # will contain archived computer imaging data archives_folder = 'archives' # will contain generated ISO images isos_folder = '/var/lib/pulse2/imaging/isos' # tool used to generate ISO file isogen_tool = '/usr/bin/genisoimage' # will contain our UUID/MAC Addr cache uuid_cache_file = os.path.join(base_folder, 'uuid-cache.txt') # our UUID/MAC Addr cache lifetime uuid_cache_lifetime = 300 # RPC replay file rpc_replay_file = os.path.join(base_folder, 'rpc-replay.pck') # RPC replay loop timer in seconds rpc_loop_timer = 60 # RPC to replay at each loop rpc_count = 10 # Interval in seconds between two RPCs rpc_interval = 2 # Package Server UUID uuid = "" if self.cp.has_option("imaging_api", 'mount_point'): imaging_mp = self.cp.get("imaging_api", 'mount_point') if self.cp.has_option('imaging_api', 'base_folder'): base_folder = self.cp.get('imaging_api', 'base_folder') if self.cp.has_option('imaging_api', 'bootloader_folder'): bootloader_folder = self.cp.get('imaging_api', 'bootloader_folder') if self.cp.has_option('imaging_api', 'cdrom_bootloader'): cdrom_bootloader = self.cp.get('imaging_api', 'cdrom_bootloader') if self.cp.has_option('imaging_api', 'bootsplash_file'): bootsplash_file = self.cp.get('imaging_api', 'bootlsplash_file') if self.cp.has_option('imaging_api', 'bootmenus_folder'): bootmenus_folder = self.cp.get('imaging_api', 'bootmenus_folder') if self.cp.has_option('imaging_api', 'diskless_folder'): diskless_folder = self.cp.get('imaging_api', 'diskless_folder') if self.cp.has_option("imaging_api", 'diskless_kernel'): diskless_kernel = self.cp.get("imaging_api", 'diskless_kernel') if self.cp.has_option("imaging_api", 'diskless_initrd'): diskless_initrd = self.cp.get("imaging_api", 'diskless_initrd') if self.cp.has_option('imaging_api', 'diskless_initrdcd'): diskless_initrdcd = self.cp.get("imaging_api", 'diskless_initrdcd') if self.cp.has_option("imaging_api", 'diskless_memtest'): diskless_memtest = self.cp.get("imaging_api", 'diskless_memtest') if self.cp.has_option('imaging_api', 'computers_folder'): computers_folder = self.cp.get('imaging_api', 'computers_folder') if self.cp.has_option('imaging_api', 'inventories_folder'): inventories_folder = self.cp.get('imaging_api', 'inventories_folder') if self.cp.has_option('imaging_api', 'masters_folder'): masters_folder = self.cp.get('imaging_api', 'masters_folder') if self.cp.has_option('imaging_api', 'postinst_folder'): postinst_folder = self.cp.get('imaging_api', 'postinst_folder') if self.cp.has_option('imaging_api', 'archives_folder'): archives_folder = self.cp.get('imaging_api', 'archives_folder') if self.cp.has_option('imaging_api', 'isos_folder'): isos_folder = self.cp.get('imaging_api', 'isos_folder') if self.cp.has_option('imaging_api', 'isogen_tool'): isogen_tool = self.cp.get('imaging_api', 'isogen_tool') if self.cp.has_option('imaging_api', 'uuid_cache_file'): uuid_cache_file = os.path.join(base_folder, self.cp.get('imaging_api', 'uuid_cache_file')) if self.cp.has_option('imaging_api', 'uuid_cache_lifetime'): uuid_cache_lifetime = self.cp.getint('imaging_api', 'uuid_cache_lifetime') if self.cp.has_option('imaging_api', 'rpc_replay_file'): rpc_replay_file = os.path.join(base_folder, self.cp.get('imaging_api', 'rpc_replay_file')) if self.cp.has_option('imaging_api', 'rpc_loop_timer'): rpc_loop_timer = self.cp.getint('imaging_api', 'rpc_loop_timer') if self.cp.has_option('imaging_api', 'rpc_count'): rpc_count = self.cp.getint('imaging_api', 'rpc_count') if self.cp.has_option('imaging_api', 'rpc_interval'): rpc_interval = self.cp.getint('imaging_api', 'rpc_interval') if self.cp.has_option("imaging_api", 'uuid'): uuid = self.cp.get("imaging_api", 'uuid') if not isUUID(uuid): raise TypeError("'%s' is not an valid UUID : in my config file, section [imaging_api], set a correct uuid." % uuid) self.imaging_api = { 'mount_point' : imaging_mp, 'base_folder' : base_folder, 'bootloader_folder' : bootloader_folder, 'bootsplash_file' : bootsplash_file, 'bootmenus_folder' : bootmenus_folder, 'cdrom_bootloader' : cdrom_bootloader, 'diskless_folder' : diskless_folder, 'diskless_kernel' : diskless_kernel, 'diskless_initrd' : diskless_initrd, 'diskless_initrdcd' : diskless_initrdcd, 'diskless_memtest' : diskless_memtest, 'computers_folder' : computers_folder, 'inventories_folder' : inventories_folder, 'masters_folder' : masters_folder, 'postinst_folder' : postinst_folder, 'archives_folder' : archives_folder, 'isos_folder' : isos_folder, 'isogen_tool' : isogen_tool, 'src' : src, 'uuid' : uuid, 'uuid_cache_file' : uuid_cache_file, 'uuid_cache_lifetime' : uuid_cache_lifetime, 'rpc_replay_file' : rpc_replay_file, 'rpc_loop_timer' : rpc_loop_timer, 'rpc_count' : rpc_count, 'rpc_interval' : rpc_interval} if self.cp.has_option("main", "package_detect_activate"): # WARN this must overide the previously defined activate if it is in the config file self.package_detect_activate = self.cp.getboolean("main", "package_detect_activate") if self.package_detect_activate and self.cp.has_option("main", "package_detect_loop"): self.package_detect_loop = self.cp.getint("main", "package_detect_loop") if self.cp.has_option("main", "package_detect_smart_method"): package_detect_smart_method = self.cp.get("main", "package_detect_smart_method") if package_detect_smart_method != 'none': package_detect_smart_method = package_detect_smart_method.split(',') self.package_detect_smart = True if 'last_time_modification' in package_detect_smart_method: self.package_detect_smart_method.append(self.SMART_DETECT_LAST) if 'check_in_loop' in package_detect_smart_method: self.package_detect_smart_method.append(self.SMART_DETECT_LOOP) if 'check_size' in package_detect_smart_method: self.package_detect_smart_method.append(self.SMART_DETECT_SIZE) else: logging.getLogger().info("dont know the package_detect_smart_method '%s'") if self.cp.has_option("main", "package_detect_smart_time"): self.package_detect_smart_time = self.cp.getint("main", "package_detect_smart_time") else: self.package_detect_smart = False if self.cp.has_option("main", "package_mirror_target"): self.package_mirror_target = self.cp.get("main", "package_mirror_target").split(' ') if (type(self.package_mirror_target) == str and self.package_mirror_target != '') or \ (type(self.package_mirror_target) == list and len(self.package_mirror_target) == 1 and self.package_mirror_target[0] != '') or \ (type(self.package_mirror_target) == list and len(self.package_mirror_target) != 1): self.package_mirror_activate = True if self.cp.has_option("main", 'package_mirror_status_file'): self.package_mirror_status_file = self.cp.get("main", 'package_mirror_status_file') if self.cp.has_option("main", 'package_mirror_loop'): self.package_mirror_loop = self.cp.getint("main", 'package_mirror_loop') if self.cp.has_option("main", 'package_mirror_command'): self.package_mirror_command = self.cp.get("main", 'package_mirror_command') if self.cp.has_option("main", 'package_mirror_command_options'): self.package_mirror_command_options = self.cp.get("main", 'package_mirror_command_options').split(' ') if self.cp.has_option("main", "package_mirror_command_options_ssh_options"): self.package_mirror_command_options_ssh_options = self.cp.get("main", 'package_mirror_command_options_ssh_options').split(' ') if self.cp.has_option("main", 'package_mirror_level0_command_options'): self.package_mirror_level0_command_options = self.cp.get("main", 'package_mirror_level0_command_options').split(' ') if self.cp.has_option("main", "package_global_mirror_activate"): self.package_global_mirror_activate = self.cp.getboolean("main", "package_global_mirror_activate") if self.cp.has_option("main", "package_global_mirror_loop"): self.package_global_mirror_loop = self.cp.getint("main", "package_global_mirror_loop") if self.cp.has_option("main", "package_global_mirror_command_options"): self.package_global_mirror_command_options = self.cp.get("main", "package_global_mirror_command_options").split(' ') if self.cp.has_option("main", "real_package_deletion"): self.real_package_deletion = self.cp.getboolean("main", "real_package_deletion") if self.cp.has_option("main", "mm_assign_algo"): self.mm_assign_algo = self.cp.get("main", 'mm_assign_algo') if self.cp.has_option("main", "up_assign_algo"): self.up_assign_algo = self.cp.get("main", 'up_assign_algo')