def main(argv=sys.argv[1:]): parser = argparse.ArgumentParser( prog='VirtualBMC server', description='A virtual BMC server for controlling virtual instances', ) parser.add_argument('--version', action='version', version=virtualbmc.__version__) parser.add_argument('--foreground', action='store_true', default=False, help='Do not daemonize') args = parser.parse_args(argv) pid_file = CONF['default']['pid_file'] try: with open(pid_file) as f: pid = int(f.read()) os.kill(pid, 0) except Exception: pass else: LOG.error('server PID #%(pid)d still running', {'pid': pid}) return 1 def wrap_with_pidfile(func, pid): dir_name = os.path.dirname(pid_file) if not os.path.exists(dir_name): os.makedirs(dir_name, mode=0o700) try: with tempfile.NamedTemporaryFile(mode='w+t', dir=dir_name, delete=False) as f: f.write(str(pid)) os.rename(f.name, pid_file) func() except Exception as e: LOG.error('%(error)s', {'error': e}) return 1 finally: try: os.unlink(pid_file) except Exception: pass if args.foreground: return wrap_with_pidfile(control.application, os.getpid()) else: with utils.detach_process() as pid: return wrap_with_pidfile(control.application, pid)
def start(self, domain_name): domain_path = os.path.join(self.config_dir, domain_name) if not os.path.exists(domain_path): raise exception.DomainNotFound(domain=domain_name) bmc_config = self._parse_config(domain_name) # check libvirt's connection and domain prior to starting the BMC utils.check_libvirt_connection_and_domain( bmc_config['libvirt_uri'], domain_name, sasl_username=bmc_config['libvirt_sasl_username'], sasl_password=bmc_config['libvirt_sasl_password']) # mask the passwords if requested log_config = bmc_config.copy() if not CONF['default']['show_passwords']: log_config = utils.mask_dict_password(bmc_config) LOG.debug( 'Starting a Virtual BMC for domain %(domain)s with the ' 'following configuration options: %(config)s', { 'domain': domain_name, 'config': ' '.join(['%s="%s"' % (k, log_config[k]) for k in log_config]) }) with utils.detach_process() as pid_num: try: vbmc = VirtualBMC(**bmc_config) except Exception as e: msg = ('Error starting a Virtual BMC for domain %(domain)s. ' 'Error: %(error)s' % { 'domain': domain_name, 'error': e }) LOG.error(msg) raise exception.VirtualBMCError(msg) # Save the PID number pidfile_path = os.path.join(domain_path, 'pid') with open(pidfile_path, 'w') as f: f.write(str(pid_num)) LOG.info('Virtual BMC for domain %s started', domain_name) vbmc.listen(timeout=CONF['ipmi']['session_timeout'])
def test_detach_process(self, mock_os): # 2nd value > 0 so _exit get called and we can assert that we've # killed the parent's process mock_os.fork.side_effect = (0, 999) mock_os.devnull = os.devnull with utils.detach_process() as pid: self.assertEqual(0, pid) # assert fork() has been called twice expected_fork_calls = [mock.call()] * 2 self.assertEqual(expected_fork_calls, mock_os.fork.call_args_list) mock_os.setsid.assert_called_once_with() mock_os.chdir.assert_called_once_with('/') mock_os.umask.assert_called_once_with(0) mock_os._exit.assert_called_once_with(0)