def test__calls_DiscoverPod_on_all_clients(self): rack_ids = [factory.make_name("system_id") for _ in range(3)] pod = DiscoveredPod( architectures=["amd64/generic"], cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), hints=DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), ), ) clients = [] for rack_id in rack_ids: client = Mock() client.ident = rack_id client.return_value = succeed({"pod": pod}) clients.append(client) self.patch(pods_module, "getAllClients").return_value = clients discovered = yield discover_pod(factory.make_name("pod"), {}) self.assertEquals(({rack_id: pod for rack_id in rack_ids}, {}), discovered)
def test_returns_discovered_pod_and_errors(self): pod_type = factory.make_name("pod") pod = DiscoveredPod( architectures=["amd64/generic"], cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), hints=DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), ), ) clients = [] client = Mock() error_rack_id = factory.make_name("system_id") client.ident = error_rack_id exception = UnknownPodType(pod_type) client.return_value = fail(exception) clients.append(client) valid_rack_id = factory.make_name("system_id") client = Mock() client.ident = valid_rack_id client.return_value = succeed({"pod": pod}) clients.append(client) self.patch(pods_module, "getAllClients").return_value = clients discovered = yield discover_pod(pod_type, {}) self.assertEqual( ({valid_rack_id: pod}, {error_rack_id: exception}), discovered )
def test__handles_timeout(self): def defer_way_later(*args, **kwargs): # Create a defer that will finish in 1 minute. return deferLater(reactor, 60 * 60, lambda: None) rack_id = factory.make_name("system_id") client = Mock() client.ident = rack_id client.side_effect = defer_way_later self.patch(pods_module, "getAllClients").return_value = [client] discovered = yield discover_pod(factory.make_name("pod"), {}, timeout=0.5) self.assertThat(discovered[0], Equals({})) self.assertThat(discovered[1], MatchesDict({rack_id: IsInstance(CancelledError)}))
def discover_and_sync_pod(self): """Discover and sync the pod information.""" def update_db(result): discovered_pod, discovered = result # When called with an instance that has no name, be sure to set # it before going any further. If this is a new instance this will # also create it in the database. if not self.instance.name: self.instance.set_random_name() self.instance.sync(discovered_pod, self.request.user) # Save which rack controllers can route and which cannot. discovered_rack_ids = [ rack_id for rack_id, _ in discovered[0].items() ] for rack_controller in RackController.objects.all(): routable = rack_controller.system_id in discovered_rack_ids bmc_route_model = BMCRoutableRackControllerRelationship relation, created = (bmc_route_model.objects.get_or_create( bmc=self.instance.as_bmc(), rack_controller=rack_controller, defaults={'routable': routable})) if not created and relation.routable != routable: relation.routable = routable relation.save() return self.instance if isInIOThread(): # Running in twisted reactor, do the work inside the reactor. d = discover_pod(self.instance.power_type, self.instance.power_parameters, pod_id=self.instance.id, name=self.instance.name) d.addCallback(lambda discovered: (get_best_discovered_result(discovered), discovered)) def catch_no_racks(result): discovered_pod, discovered = result if discovered_pod is None: raise PodProblem( "Unable to start the pod discovery process. " "No rack controllers connected.") return discovered_pod, discovered def wrap_errors(failure): if failure.check(PodProblem): return failure else: raise PodProblem(str(failure.value)) d.addCallback(catch_no_racks) d.addCallback(partial(deferToDatabase, transactional(update_db))) d.addErrback(wrap_errors) return d else: # Perform the actions inside the executing thread. try: discovered = discover_pod(self.instance.power_type, self.instance.power_parameters, pod_id=self.instance.id, name=self.instance.name) except Exception as exc: raise PodProblem(str(exc)) from exc # Use the first discovered pod object. All other objects are # ignored. The other rack controllers that also provided a result # can route to the pod. try: discovered_pod = get_best_discovered_result(discovered) except Exception as error: raise PodProblem(str(error)) if discovered_pod is None: raise PodProblem("Unable to start the pod discovery process. " "No rack controllers connected.") return update_db((discovered_pod, discovered))
def discover_and_sync_pod(self): """Discover and sync the pod information.""" def update_db(result): discovered_pod, discovered = result if self.request is not None: user = self.request.user else: user = self.user # If this is a new instance it will be stored in the database # at the end of sync. self.instance.sync(discovered_pod, user) # Save which rack controllers can route and which cannot. discovered_rack_ids = [ rack_id for rack_id, _ in discovered[0].items() ] for rack_controller in RackController.objects.all(): routable = rack_controller.system_id in discovered_rack_ids bmc_route_model = BMCRoutableRackControllerRelationship relation, created = bmc_route_model.objects.get_or_create( bmc=self.instance.as_bmc(), rack_controller=rack_controller, defaults={"routable": routable}, ) if not created and relation.routable != routable: relation.routable = routable relation.save() return self.instance if isInIOThread(): # Running in twisted reactor, do the work inside the reactor. d = discover_pod( self.instance.power_type, self.instance.power_parameters, pod_id=self.instance.id, name=self.instance.name, ) d.addCallback(lambda discovered: ( get_best_discovered_result(discovered), discovered, )) def catch_no_racks(result): discovered_pod, discovered = result if discovered_pod is None: raise PodProblem( "Unable to start the pod discovery process. " "No rack controllers connected.") return discovered_pod, discovered def wrap_errors(failure): if failure.check(PodProblem): return failure else: log.err(failure, "Failed to discover pod.") raise PodProblem(str(failure.value)) d.addCallback(catch_no_racks) d.addCallback(partial(deferToDatabase, transactional(update_db))) d.addCallback(request_commissioning_results) d.addErrback(wrap_errors) return d else: # Perform the actions inside the executing thread. try: discovered = discover_pod( self.instance.power_type, self.instance.power_parameters, pod_id=self.instance.id, name=self.instance.name, ) except Exception as exc: raise PodProblem(str(exc)) from exc # Use the first discovered pod object. All other objects are # ignored. The other rack controllers that also provided a result # can route to the pod. try: discovered_pod = get_best_discovered_result(discovered) except Exception as error: raise PodProblem(str(error)) if discovered_pod is None: raise PodProblem("Unable to start the pod discovery process. " "No rack controllers connected.") update_db((discovered_pod, discovered)) # The data isn't committed to the database until the transaction is # complete. The commissioning results must be sent after the # transaction completes so the metadata server can process the # data. post_commit_do( reactor.callLater, 0, request_commissioning_results, self.instance, ) # Run commissioning request here return self.instance