def test_get_request_params_returns_params(self): factory.make_RegionRackController() params = { "data": base64.b64encode(json.dumps(get_maas_stats()).encode()).decode() } self.assertEquals(params, get_request_params())
def test_issue_resolved_removes_notification(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_versions_info( c1, SnapVersionsInfo( current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, cohort="abc", ), ) ControllerInfo.objects.set_versions_info( c2, SnapVersionsInfo(current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, ), ) self.assertTrue( Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).exists()) # remove the cohort ControllerInfo.objects.set_versions_info( c1, SnapVersionsInfo(current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, ), ) self.assertFalse( Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).exists())
def test_get_maas_stats(self): # Make one component of everything factory.make_RegionRackController() factory.make_RegionController() factory.make_RackController() factory.make_Machine(cpu_count=2, memory=200) factory.make_Machine(cpu_count=3, memory=100) factory.make_Device() stats = get_maas_stats() machine_stats = get_machine_stats() # Due to floating point calculation subtleties, sometimes the value the # database returns is off by one compared to the value Python # calculates, so just get it directly from the database for the test. total_storage = machine_stats['total_storage'] compare = { "controllers": { "regionracks": 1, "regions": 1, "racks": 1, }, "nodes": { "machines": 2, "devices": 1, }, "machine_stats": { "total_cpu": 5, "total_mem": 300, "total_storage": total_storage, }, } self.assertEquals(stats, json.dumps(compare))
def test_different_snap_cohorts(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_versions_info( c1, SnapVersionsInfo( current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, cohort="abc", ), ) ControllerInfo.objects.set_versions_info( c2, SnapVersionsInfo( current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, cohort="xyz", ), ) notification = Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).first() self.assertIn( "Controllers have different installation sources.", notification.message, )
def test_get_maas_stats(self): # Make one component of everything factory.make_RegionRackController() factory.make_RegionController() factory.make_RackController() factory.make_Machine(cpu_count=2, memory=200, status=NODE_STATUS.READY) factory.make_Machine(status=NODE_STATUS.READY) factory.make_Machine(status=NODE_STATUS.NEW) for _ in range(4): factory.make_Machine(status=NODE_STATUS.ALLOCATED) factory.make_Machine( cpu_count=3, memory=100, status=NODE_STATUS.FAILED_DEPLOYMENT ) for _ in range(2): factory.make_Machine(status=NODE_STATUS.DEPLOYED) factory.make_Device() factory.make_Device() subnets = Subnet.objects.all() v4 = [net for net in subnets if net.get_ip_version() == 4] v6 = [net for net in subnets if net.get_ip_version() == 6] stats = get_maas_stats() machine_stats = get_machine_stats() # Due to floating point calculation subtleties, sometimes the value the # database returns is off by one compared to the value Python # calculates, so just get it directly from the database for the test. total_storage = machine_stats["total_storage"] expected = { "controllers": {"regionracks": 1, "regions": 1, "racks": 1}, "nodes": {"machines": 10, "devices": 2}, "machine_stats": { "total_cpu": 5, "total_mem": 300, "total_storage": total_storage, }, "machine_status": { "new": 1, "ready": 2, "allocated": 4, "deployed": 2, "commissioning": 0, "testing": 0, "deploying": 0, "failed_deployment": 1, "failed_commissioning": 0, "failed_testing": 0, "broken": 0, }, "network_stats": { "spaces": Space.objects.count(), "fabrics": Fabric.objects.count(), "vlans": VLAN.objects.count(), "subnets_v4": len(v4), "subnets_v6": len(v6), }, } self.assertEqual(json.loads(stats), expected)
def test_version_with_highest_count(self): c1 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c1, "3.0.0") c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c2, "3.0.0") c3 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c3, "3.1.0") self.assertEqual(get_maas_version(), MAASVersion.from_string("3.0.0"))
def test__assumes_old_controller_if_version_unknown(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c1, "2.3.0") self.assertThat(get_version_notifications().count(), Equals(1)) self.assertThat( get_version_notifications().first().render(), Equals(UNKNOWN_VERSION_MISMATCH_NOTIFICATION.format( system_id=c2.system_id, hostname=c2.hostname)))
def test__out_of_date_controller_generates_concise_notification(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c1, "2.3.0-500-g1") ControllerInfo.objects.set_version(c2, "2.3.1-500-g1") self.assertThat(get_version_notifications().count(), Equals(1)) self.assertThat( get_version_notifications().first().render(), Equals(KNOWN_VERSION_MISMATCH_NOTIFICATION.format( system_id=c1.system_id, hostname=c1.hostname, v1="2.3.0")))
def test_push_stats_to_prometheus(self): factory.make_RegionRackController() maas_name = 'random.maas' push_gateway = '127.0.0.1:2000' mock_prom_cli = self.patch(stats, "prom_cli") push_stats_to_prometheus(maas_name, push_gateway) self.assertThat( mock_prom_cli.push_to_gateway, MockCalledOnceWith( push_gateway, job="stats_for_%s" % maas_name, registry=mock_prom_cli.CollectorRegistry()))
def test_different_issue_new_notification(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_versions_info( c1, SnapVersionsInfo( current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, channel={ "track": "3.0", "risk": "stable" }, ), ) ControllerInfo.objects.set_versions_info( c2, SnapVersionsInfo( current={ "version": "3.0.0-111-g.aaa", "revision": "1234" }, channel={ "track": "3.0", "risk": "beta" }, ), ) notification1 = Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).first() self.assertIn( "Controllers have different installation sources.", notification1.message, ) ControllerInfo.objects.set_versions_info( c2, SnapVersionsInfo( current={ "version": "3.0.2-222-g.bbb", "revision": "5678" }, channel={ "track": "3.0", "risk": "stable" }, ), ) notification2 = Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).first() self.assertIn( "Controllers have different versions.", notification2.message, ) self.assertNotEqual(notification1.id, notification2.id)
def test__revno_differences_cause_full_version_to_be_shown(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c1, "2.3.0~beta2-6000-g123abc") ControllerInfo.objects.set_version(c2, "2.3.0~beta2-6001-g234bcd") self.assertThat(get_version_notifications().count(), Equals(1)) self.assertThat( get_version_notifications().first().render(), Equals(KNOWN_VERSION_MISMATCH_NOTIFICATION.format( system_id=c1.system_id, hostname=c1.hostname, v1="2.3.0~beta2 (6000-g123abc)")))
def test_combine_versions_up_to_qualifier(self): c1 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c1, "3.0.0~beta1-123-g.asdf") c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c2, "3.0.0~beta2-456-g.cafe") c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c2, "3.0.0~beta2-789-g.abcd") c3 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c3, "3.1.0") self.assertEqual(get_maas_version(), MAASVersion.from_string("3.0.0~beta2"))
def test_disabled_configuration_causes_interface_update(self): factory.make_RegionRackController() factory.make_RegionController() factory.make_RackController() mock_update_discovery_state = self.patch( Controller, "update_discovery_state") Config.objects.set_config('network_discovery', 'disabled') self.expectThat( mock_update_discovery_state, MockCallsMatch(*[call(NetworkDiscoveryConfig( active=False, passive=False))] * 3))
def test_push_stats_to_prometheus(self): factory.make_RegionRackController() maas_name = 'random.maas' push_gateway = '127.0.0.1:2000' registry_mock = self.patch(prometheus, "CollectorRegistry") self.patch(prometheus, "Gauge") mock = self.patch(prometheus, "push_to_gateway") push_stats_to_prometheus(maas_name, push_gateway) self.assertThat( mock, MockCalledOnceWith(push_gateway, job="stats_for_%s" % maas_name, registry=registry_mock()))
def test__version_qualifiers_considered(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() # Note: the revno and git revision are intentionally identical here, # so we know they don't affect the comparison of qualifiers, and we # know that useless information won't appear in the notification. ControllerInfo.objects.set_version(c1, "2.3.0~alpha1-500-g1") ControllerInfo.objects.set_version(c2, "2.3.0~alpha2-500-g1") self.assertThat(get_version_notifications().count(), Equals(1)) self.assertThat( get_version_notifications().first().render(), Equals(KNOWN_VERSION_MISMATCH_NOTIFICATION.format( system_id=c1.system_id, hostname=c1.hostname, v1="2.3.0~alpha1")))
def test_update_status_update_already_completed(self): c1 = factory.make_RegionRackController() ControllerInfo.objects.set_versions_info( c1, DebVersionsInfo( current={"version": "3.0.0-111.aaa"}, update={"version": "3.0.1-222-g.bbb"}, ), ) ControllerInfo.objects.set_versions_info( c1, DebVersionsInfo(current={"version": "3.0.1-222-g.bbb"}, ), ) notification1 = Notification.objects.filter( ident=UPGRADE_STATUS_NOTIFICATION_IDENT, ).first() # report again, but with no change ControllerInfo.objects.set_versions_info( c1, DebVersionsInfo(current={"version": "3.0.1-222-g.bbb"}, ), ) notification2 = Notification.objects.filter( ident=UPGRADE_STATUS_NOTIFICATION_IDENT, ).first() self.assertEqual( notification2.render(), "MAAS has been updated to version 3.0.1.", ) self.assertEqual( notification2.context, { "status": "completed", "version": "3.0.1" }, ) self.assertEqual(notification1.id, notification2.id)
def test_sorts_controllerversioninfo_by_most_recent_version_first(self): c1 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c1, "2.3.0") c2 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c2, "2.4.0") c3 = factory.make_RegionRackController() ControllerInfo.objects.set_version(c3, "2.3.5") version_info = ControllerInfo.objects.get_controller_version_info() # Should have returend a list of ControllerVersionInfo objects. for i in range(len(version_info)): self.assertThat(isinstance(version_info[i], ControllerVersionInfo), Is(True)) # The versions should be in descending order. self.assertThat(version_info[0].version, Equals("2.4.0")) self.assertThat(version_info[1].version, Equals("2.3.5")) self.assertThat(version_info[2].version, Equals("2.3.0"))
def test_list_num_queries_is_the_expected_number(self): owner = factory.make_admin() for _ in range(10): node = factory.make_RegionRackController(owner=owner) commissioning_script_set = factory.make_ScriptSet( node=node, result_type=RESULT_TYPE.COMMISSIONING) testing_script_set = factory.make_ScriptSet( node=node, result_type=RESULT_TYPE.TESTING) node.current_commissioning_script_set = commissioning_script_set node.current_testing_script_set = testing_script_set node.save() for __ in range(10): factory.make_ScriptResult(status=SCRIPT_STATUS.PASSED, script_set=commissioning_script_set) factory.make_ScriptResult(status=SCRIPT_STATUS.PASSED, script_set=testing_script_set) handler = ControllerHandler(owner, {}, None) queries_one, _ = count_queries(handler.list, {'limit': 1}) queries_total, _ = count_queries(handler.list, {}) # This check is to notify the developer that a change was made that # affects the number of queries performed when doing a node listing. # It is important to keep this number as low as possible. A larger # number means regiond has to do more work slowing down its process # and slowing down the client waiting for the response. self.assertEqual( queries_one, 3, "Number of queries has changed; make sure this is expected.") self.assertEqual( queries_total, 3, "Number of queries has changed; make sure this is expected.")
def test_create_region_event_creates_region_event(self): region = factory.make_RegionRackController() self.patch(event_module, "get_maas_id").return_value = region.system_id Event.objects.create_region_event( event_type=EVENT_TYPES.REGION_IMPORT_ERROR, user=region.owner) self.assertIsNotNone( EventType.objects.get(name=EVENT_TYPES.REGION_IMPORT_ERROR)) self.assertIsNotNone(Event.objects.get(node=region))
def test_deleting_controller_causes_old_notifications_to_go_away(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionController() ControllerInfo.objects.set_version(c1, "2.3.0~beta2-6000-g123abc") ControllerInfo.objects.set_version(c2, "2.3.0~beta2-6001-g234bcd") self.assertThat(get_version_notifications().count(), Equals(1)) c2.delete() self.assertThat(get_version_notifications().count(), Equals(0))
def test_different_versions(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_versions_info( c1, DebVersionsInfo(current={"version": "3.0.0-111-g.aaa"}, ), ) ControllerInfo.objects.set_versions_info( c2, DebVersionsInfo(current={"version": "3.0.1-222-g.bbb"}, ), ) notification = Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).first() self.assertIn( "Controllers have different versions.", notification.message, )
def setUp(self): super().setUp() self.region = factory.make_RegionRackController() # This is so get_running_controller() works properly. RegionController = self.patch(reverse_dns_module, "RegionController") RegionController.objects = Mock() RegionController.objects.get_running_controller = Mock() RegionController.objects.get_running_controller.return_value = ( self.region)
def test_single_controller_never_generates_notifications(self): c1 = factory.make_RegionRackController() self.assertThat(get_version_notifications().count(), Equals(0)) ControllerInfo.objects.set_version(c1, "2.3.0") self.assertThat(get_version_notifications().count(), Equals(0)) ControllerInfo.objects.set_version(c1, None) self.assertThat(get_version_notifications().count(), Equals(0)) ControllerInfo.objects.set_version(c1, "") self.assertThat(get_version_notifications().count(), Equals(0))
def test_read_all(self): self.become_admin() for _ in range(3): factory.make_DNSResource() factory.make_RegionRackController() uri = get_dnsresources_uri() response = self.client.get(uri, {"all": "true"}) self.assertEqual(http.client.OK, response.status_code, response.content) expected_ids = [ dnsresource.id for dnsresource in get_dnsresource_queryset(all_records=True) ] result_ids = [ dnsresource["id"] for dnsresource in json.loads( response.content.decode(settings.DEFAULT_CHARSET)) ] self.assertItemsEqual(expected_ids, result_ids)
def make_region_rack_with_address(space): region = factory.make_RegionRackController() iface = factory.make_Interface(node=region) cidr4 = factory.make_ipv4_network(24) subnet4 = factory.make_Subnet(space=space, cidr=cidr4) cidr6 = factory.make_ipv6_network(64) subnet6 = factory.make_Subnet(space=space, cidr=cidr6) sip4 = factory.make_StaticIPAddress(interface=iface, subnet=subnet4) sip6 = factory.make_StaticIPAddress(interface=iface, subnet=subnet6) return region, sip4, sip6
def test_same_upgrade(self): c1 = factory.make_RegionRackController() c2 = factory.make_RegionRackController() ControllerInfo.objects.set_versions_info( c1, DebVersionsInfo( current={"version": "3.0.0-111-g.aaa"}, update={"version": "3.0.1-222-g.bbb"}, ), ) ControllerInfo.objects.set_versions_info( c2, DebVersionsInfo( current={"version": "3.0.0-111-g.aaa"}, update={"version": "3.0.1-222-g.bbb"}, ), ) self.assertFalse( Notification.objects.filter( ident=UPGRADE_ISSUE_NOTIFICATION_IDENT).exists())
def test_list_switches_includes_link_type_controller(self): owner = factory.make_admin() handler = SwitchHandler(owner, {}, None) controller1 = factory.make_RackController(owner=owner) controller2 = factory.make_RegionController(owner=owner) controller3 = factory.make_RegionRackController(owner=owner) factory.make_Switch(node=controller1) factory.make_Switch(node=controller2) factory.make_Switch(node=controller3) self.assertItemsEqual( ['controller', 'controller', 'controller'], [result['link_type'] for result in handler.list({})])
def test_get_maas_stats(self): # Make one component of everything factory.make_RegionRackController() factory.make_RegionController() factory.make_RackController() factory.make_Machine() factory.make_Device() stats = get_maas_stats() compare = { "controllers": { "regionracks": 1, "regions": 1, "racks": 1, }, "nodes": { "machines": 1, "devices": 1, }, } self.assertEquals(stats, json.dumps(compare))
def test_dehydrate_includes_tags(self): owner = factory.make_admin() handler = ControllerHandler(owner, {}, None) region = factory.make_RegionRackController() tags = [] for _ in range(3): tag = factory.make_Tag(definition="") tag.node_set.add(region) tag.save() tags.append(tag.name) result = handler.list({}) self.assertEqual(tags, result[0].get("tags"))
def test_DELETE_force_not_required_for_pod_region_rack(self): self.become_admin() vlan = factory.make_VLAN() factory.make_Subnet(vlan=vlan) rack = factory.make_RegionRackController(vlan=vlan) ip = factory.make_StaticIPAddress(interface=rack.interface_set.first()) factory.make_Pod(ip_address=ip) mock_async_delete = self.patch(Pod, "async_delete") response = self.client.delete(self.get_region_uri(rack), QUERY_STRING=urlencode({'force': 'true'}, doseq=True)) self.assertEqual( http.client.NO_CONTENT, response.status_code, explain_unexpected_response(http.client.NO_CONTENT, response)) self.assertThat(mock_async_delete, MockNotCalled())