def __init__(self, config_dir, count, osds_per_host, port=8761, prefix=PREFIX, domain=DOMAIN): super(MinionSim, self).__init__() self._config_dir = config_dir self._count = count self._server = None self._server_available = threading.Event() self.minions = {} def get_dns(index): host = "{0}{1:03d}".format(prefix, index) return host, "{0}.{1}".format(host, domain) config_file = os.path.join(self._config_dir, 'cluster.json') self.cluster = CephCluster(config_file) if not os.path.exists(config_file): self.cluster.create([get_dns(i)[1] for i in range(0, self._count)], osds_per_host=osds_per_host) self.cluster.save() # An XMLRPC service for the minions' fake ceph plugins to # get their state self._server = SimpleXMLRPCServer(("localhost", port), allow_none=True) self._server.register_instance(self.cluster) rpc_url = "http://localhost:%s" % port for i in range(0, self._count): hostname, fqdn = get_dns(i) self.minions[fqdn] = MinionLauncher(rpc_url, self._config_dir, hostname, fqdn, self.cluster) # Quick smoke test that these methods aren't going # to throw exceptions (rather stop now than get exceptions # remotely) for minion in self.minions.values(): self.cluster.get_stats(minion.fqdn)
def setUp(self): super(TestMon, self).setUp() # I'm using CephCluster to generate the status objects to use as fixtures, I'm not # actually running the simulator or anything like that because this is a unit test. cluster = CephCluster() cluster.create(self.SERVERS) self.fsid = cluster.fsid # This will appear to be a completely happy healthy quorum of mons self.mon_status = msgpack.unpackb( cluster.get_cluster_object('ceph_fake', 'mon_status', None).data)['data'] # XXX hmm, perhaps synthesizing this stuff should go into # ceph_cluster and then it be sensibly kept up to date with # synthesized quorum changes. self.server1_status = deepcopy(self.mon_status) self.server2_status = deepcopy(self.mon_status) self.server3_status = deepcopy(self.mon_status) for (server_status, name, rank, state) in [ (self.server1_status, 'server1', 0, 'leader'), (self.server2_status, 'server2', 1, 'peon'), (self.server3_status, 'server3', 2, 'peon'), ]: server_status['name'] = name server_status['rank'] = rank server_status['state'] = state self.service_status = [{ 'id': 'server1', 'type': 'mon', 'cluster': cluster.name, 'fsid': cluster.fsid, 'status': self.server1_status, 'server': 'server1', 'running': True }, { 'id': 'server1', 'type': 'mon', 'cluster': cluster.name, 'fsid': cluster.fsid, 'status': self.server2_status, 'server': 'server2', 'running': True }, { 'id': 'server1', 'type': 'mon', 'cluster': cluster.name, 'fsid': cluster.fsid, 'status': self.server3_status, 'server': 'server3', 'running': True }] self.rpc.get_sync_object = mock.Mock(return_value=self.mon_status) self.rpc.status_by_service = mock.Mock( return_value=self.service_status)
class MinionSim(threading.Thread): def __init__(self, config_dir, count, osds_per_host, port=8761, prefix=PREFIX, domain=DOMAIN): super(MinionSim, self).__init__() self._config_dir = config_dir self._count = count self._server = None self._server_available = threading.Event() self.minions = {} def get_dns(index): host = "{0}{1:03d}".format(prefix, index) return host, "{0}.{1}".format(host, domain) config_file = os.path.join(self._config_dir, 'cluster.json') self.cluster = CephCluster(config_file) if not os.path.exists(config_file): self.cluster.create([get_dns(i)[1] for i in range(0, self._count)], osds_per_host=osds_per_host) self.cluster.save() # An XMLRPC service for the minions' fake ceph plugins to # get their state self._server = SimpleXMLRPCServer(("localhost", port), allow_none=True) self._server.register_instance(self.cluster) rpc_url = "http://localhost:%s" % port for i in range(0, self._count): hostname, fqdn = get_dns(i) self.minions[fqdn] = MinionLauncher(rpc_url, self._config_dir, hostname, fqdn, self.cluster) # Quick smoke test that these methods aren't going # to throw exceptions (rather stop now than get exceptions # remotely) for minion in self.minions.values(): self.cluster.get_stats(minion.fqdn) def get_minion_fqdns(self): return [m.fqdn for m in self.minions.values()] def start(self): super(MinionSim, self).start() self._server_available.wait() def run(self): # A thread to generate some synthetic activity on the synthetic cluster load_gen = LoadGenerator(self.cluster) load_gen.start() self.start_minions() self._server_available.set() log.debug("Starting XMLRPC server...") self._server.serve_forever() self._server.server_close() log.debug("XMLRPC server terminated, stopping threads") log.debug("Stopping load gen") load_gen.stop() load_gen.join() log.debug("Stopping minions") self.halt_minions() log.debug("Saving state") self.cluster.save() log.debug("Complete.") def stop(self): # FIXME should stop the minions before the XMLRPC server, because otherwise # minions start getting XMLRPC errors self._server.shutdown() def halt_minions(self): for minion in self.minions.values(): minion.stop() for minion in self.minions.values(): minion.join() def start_minions(self): for minion in self.minions.values(): minion.start() def halt_minion(self, minion_id): self.minions[minion_id].stop() self.minions[minion_id].join() def start_minion(self, minion_id): self.minions[minion_id].start()