def build_widget(self, **kwargs): def remove_p(charm_class): n = self.pc.assignment_machine_count_for_charm(charm_class) return n > 0 def not_conflicted_p(cc): state, _, _ = self.pc.get_charm_state(cc) return state != CharmState.CONFLICTED actions = [(remove_p, 'Remove', self.do_remove), (not_conflicted_p, 'Add', self.do_add)] self.unrequired_undeployed_sl = ServicesList(self.pc, actions, actions, ignore_deployed=True, title="Un-Deployed") self.deployed_sl = ServicesList(self.pc, actions, actions, deployed_only=True, show_placements=True, title="Deployed Services") self.assigned_sl = ServicesList(self.pc, actions, actions, assigned_only=True, show_placements=True, title="Services to be Deployed") self.buttons = [] self.button_grid = GridFlow(self.buttons, 22, 1, 1, 'center') self.pile1 = Pile([self.button_grid, self.assigned_sl, self.unrequired_undeployed_sl]) self.pile2 = Pile([self.deployed_sl]) return LineBox(Columns([self.pile1, self.pile2]), title="Add Services")
def build_widgets(self): self.deploy_view = DeployView(self.display_controller, self.placement_controller, self.placement_view) def not_conflicted_p(cc): state, _, _ = self.placement_controller.get_charm_state(cc) return state != CharmState.CONFLICTED actions = [(not_conflicted_p, "Choose Machine", self.placement_view.do_show_machine_chooser)] subordinate_actions = [(not_conflicted_p, "Add", self.do_place_subordinate)] self.required_services_list = ServicesList(self.placement_controller, actions, subordinate_actions, ignore_assigned=True, ignore_deployed=True, show_type='required', show_constraints=True, title="Required Services") self.additional_services_list = ServicesList(self.placement_controller, actions, subordinate_actions, show_type='non-required', show_constraints=True, title="Additional " "Services") autoplace_func = self.placement_view.do_autoplace self.autoplace_button = AttrMap( Button("Auto-place Remaining Services", on_press=autoplace_func), 'button_secondary', 'button_secondary focus') clear_all_func = self.placement_view.do_clear_all self.clear_all_button = AttrMap( Button("Clear all Placements", on_press=clear_all_func), 'button_secondary', 'button_secondary focus') self.required_services_pile = Pile( [self.required_services_list, Divider()]) self.additional_services_pile = Pile( [self.additional_services_list, Divider()]) self.top_buttons = [] self.top_button_grid = GridFlow(self.top_buttons, 36, 1, 0, 'center') pl = [ Text(('subheading', "Services"), align='center'), Divider(), self.top_button_grid, Divider(), self.deploy_view, Divider(), self.required_services_pile, Divider(), self.additional_services_pile ] self.main_pile = Pile(pl) return self.main_pile
def test_machine_checks_constraints(self, mock_servicewidgetclass): mock_machine = make_fake_machine('fm', {'cpu_count': 0, 'storage': 0, 'memory': 0}) sl = ServicesList(self.pc, self.actions, self.sub_actions, machine=mock_machine) self.assertEqual(len(sl.service_widgets), 0)
def build_widgets(self): instructions = Text("Remove services from {}".format( self.machine.hostname)) self.machine_widget = MachineWidget(self.machine, self.controller, show_hardware=True) def show_remove_p(cc): md = self.controller.get_assignments(cc) for atype, ms in md.items(): hostnames = [m.hostname for m in ms] if self.machine.hostname in hostnames: return True return False actions = [(show_remove_p, 'Remove', self.do_remove)] self.services_list = ServicesList(self.controller, actions, actions, machine=self.machine) close_button = AttrMap(Button('X', on_press=self.close_pressed), 'button_secondary', 'button_secondary focus') p = Pile([ GridFlow([close_button], 5, 1, 0, 'right'), instructions, Divider(), self.machine_widget, Divider(), self.services_list ]) return LineBox(p, title="Remove Services")
def test_no_machine_no_constraints(self, mock_servicewidgetclass): with patch.object(self.pc, 'charm_classes') as mock_classesfunc: fc = MagicMock(name='fakeclass1') fc.required_num_units.return_value = 1 fc.constraints = {'cpu_count': 1000} mock_classesfunc.return_value = [fc] sl = ServicesList(self.pc, self.actions, self.sub_actions) self.assertEqual(len(sl.service_widgets), 1)
def test_do_not_show_assigned(self, mock_servicewidgetclass): mock_machine = make_fake_machine('fm', {'cpu_count': 0, 'storage': 0, 'memory': 0}) self.pc.assign(mock_machine, CharmNovaCompute, AssignmentType.LXC) sl = ServicesList(self.pc, self.actions, self.sub_actions, machine=mock_machine) classes = [sw.charm_class for sw in sl.service_widgets] self.assertTrue(CharmNovaCompute not in classes)
def test_widgets_config(self, mock_servicewidgetclass): for show_constraints in [False, True]: sl = ServicesList(self.pc, self.actions, self.sub_actions, show_constraints=show_constraints) mock_servicewidgetclass.assert_any_call( CharmNovaCompute, self.pc, self.actions, show_constraints, show_placements=sl.show_placements) mock_servicewidgetclass.reset_mock()
def test_show_type(self, mock_servicewidgetclass): """Test combinations of show_type values. This tests three values of show_type with three return values for is_required(): all required, no required, and 1/3 required. It's all lumped in one test to consolidate setup. """ mock_sw1 = MagicMock(name='sw1') mock_sw1.charm_class.charm_name = 'cc1' mock_sw2 = MagicMock(name='sw2') mock_sw2.charm_class.charm_name = 'cc2' mock_sw3 = MagicMock(name='sw3') mock_sw3.charm_class.charm_name = 'cc3' mock_servicewidgetclass.side_effect = [mock_sw1, mock_sw2, mock_sw3] with patch.object(self.pc, 'get_charm_state') as mock_get_state: with patch.object(self.pc, 'charm_classes') as mock_classesfunc: mock_classesfunc.return_value = [ MagicMock(name='fake-class-1', charm_name='cc1'), MagicMock(name='fake-class-2', charm_name='cc2'), MagicMock(name='fake-class-3', charm_name='cc3') ] # First, test when all charms are required mock_get_state.return_value = (CharmState.REQUIRED, [], []) # rsl shows required charms rsl = ServicesList(self.pc, self.actions, self.sub_actions, machine=None, show_type='required') self.assertEqual(len(mock_get_state.mock_calls), 3) # should show all 3 self.assertEqual(len(rsl.service_widgets), 3) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] # usl shows ONLY un-required charms usl = ServicesList(self.pc, self.actions, self.sub_actions, machine=None, show_type='non-required') self.assertEqual(len(mock_get_state.mock_calls), 3) # should show 0 self.assertEqual(len(usl.service_widgets), 0) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] # asl has default show_type='all', showing all charms asl = ServicesList(self.pc, self.actions, self.sub_actions) self.assertEqual(len(mock_get_state.mock_calls), 3) # should show all 3 self.assertEqual(len(asl.service_widgets), 3) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] # next, test where no charms are required mock_get_state.return_value = (CharmState.OPTIONAL, [], []) rsl.update() self.assertEqual(len(mock_get_state.mock_calls), 3) # should show 0 charms self.assertEqual(len(rsl.service_widgets), 0) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] usl.update() self.assertEqual(len(mock_get_state.mock_calls), 3) # should show all 3 self.assertEqual(len(usl.service_widgets), 3) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] asl.update() self.assertEqual(len(mock_get_state.mock_calls), 3) # should still show all 3 self.assertEqual(len(asl.service_widgets), 3) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] # next test two un-required and one required charm: mock_get_state.side_effect = [(CharmState.OPTIONAL, [], []), (CharmState.REQUIRED, [], []), (CharmState.OPTIONAL, [], [])] rsl.update() self.assertEqual(len(mock_get_state.mock_calls), 3) # should show 1: self.assertEqual(len(rsl.service_widgets), 1) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] mock_get_state.side_effect = [(CharmState.OPTIONAL, [], []), (CharmState.REQUIRED, [], []), (CharmState.OPTIONAL, [], [])] usl.update() self.assertEqual(len(mock_get_state.mock_calls), 3) # should show two self.assertEqual(len(usl.service_widgets), 2) mock_get_state.reset_mock() mock_servicewidgetclass.reset_mock() mock_servicewidgetclass.side_effect = [ mock_sw1, mock_sw2, mock_sw3 ] mock_get_state.side_effect = [(CharmState.OPTIONAL, [], []), (CharmState.REQUIRED, [], []), (CharmState.OPTIONAL, [], [])] asl.update() self.assertEqual(len(mock_get_state.mock_calls), 3) # should still show all three self.assertEqual(len(asl.service_widgets), 3)