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")
예제 #2
0
    def build_widgets(self):
        self.services_list = ServicesList(self.placement_controller,
                                          self.display_controller,
                                          title=None)

        self.services_pile = Pile([self.services_list, Divider()])

        return self.services_pile
    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 build_widgets(self):
        self.services_list = ServicesList(self.placement_controller,
                                          self.display_controller,
                                          title=None)

        self.services_pile = Pile([self.services_list, Divider()])

        return self.services_pile
class ServicesColumn(WidgetWrap):

    """Displays dynamic list of unplaced services and associated controls
    """

    def __init__(self, display_controller, placement_controller,
                 placement_view):
        self.display_controller = display_controller
        self.placement_controller = placement_controller
        self.placement_view = placement_view
        w = self.build_widgets()
        super().__init__(w)
        self.update()

    def selectable(self):
        return True

    def build_widgets(self):
        self.services_list = ServicesList(self.placement_controller,
                                          self.display_controller,
                                          title=None)

        self.services_pile = Pile([self.services_list, Divider()])

        return self.services_pile

    def focus_top(self):
        self.update()
        self.services_list.focus_top()

    def focus_next(self):
        self.update()
        moved = self.services_list.focus_top_or_next()
        fsw = self.services_list.focused_service_widget()
        if not moved or (fsw and fsw.service.subordinate):
            self.placement_view.focus_footer()

    def update(self):
        self.services_list.update()

    def do_reset_to_defaults(self, sender):
        self.placement_controller.set_all_assignments(
            self.placement_controller.gen_defaults())

    def clear_selections(self):
        for sw in self.services_list.service_widgets:
            sw.state = ServiceWidgetState.UNSELECTED

    def select_service(self, service_name):
        self.services_list.select_service(service_name)
예제 #6
0
class ServicesColumn(WidgetWrap):
    """Displays dynamic list of unplaced services and associated controls
    """
    def __init__(self, display_controller, placement_controller,
                 placement_view):
        self.display_controller = display_controller
        self.placement_controller = placement_controller
        self.placement_view = placement_view
        w = self.build_widgets()
        super().__init__(w)
        self.update()

    def selectable(self):
        return True

    def build_widgets(self):
        self.services_list = ServicesList(self.placement_controller,
                                          self.display_controller,
                                          title=None)

        self.services_pile = Pile([self.services_list, Divider()])

        return self.services_pile

    def focus_top(self):
        self.update()
        self.services_list.focus_top()

    def focus_next(self):
        self.update()
        moved = self.services_list.focus_top_or_next()
        fsw = self.services_list.focused_service_widget()
        if not moved or (fsw and fsw.service.subordinate):
            self.placement_view.focus_footer()

    def update(self):
        self.services_list.update()

    def do_reset_to_defaults(self, sender):
        self.placement_controller.set_all_assignments(
            self.placement_controller.gen_defaults())

    def clear_selections(self):
        for sw in self.services_list.service_widgets:
            sw.state = ServiceWidgetState.UNSELECTED

    def select_service(self, service_name):
        self.services_list.select_service(service_name)
예제 #7
0
    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,
                                                     ignore_assigned=True,
                                                     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(("body", "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
예제 #8
0
class ServicesColumn(WidgetWrap):

    """Displays dynamic list of unplaced services and associated controls
    """

    def __init__(self, display_controller, placement_controller,
                 placement_view):
        self.display_controller = display_controller
        self.placement_controller = placement_controller
        self.placement_view = placement_view
        w = self.build_widgets()
        super().__init__(w)
        self.update()

    def selectable(self):
        return True

    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,
                                                     ignore_assigned=True,
                                                     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(("body", "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 update(self):
        self.deploy_view.update()
        self.required_services_list.update()
        self.additional_services_list.update()

        top_buttons = []
        unplaced = self.placement_controller.unassigned_undeployed_services()
        if len(unplaced) == 0:
            icon = SelectableIcon(" (Auto-place Remaining Services) ")
            top_buttons.append((AttrMap(icon,
                                        'disabled_button',
                                        'disabled_button_focus'),
                                self.top_button_grid.options()))

        else:
            top_buttons.append((self.autoplace_button,
                                self.top_button_grid.options()))

        top_buttons.append((self.clear_all_button,
                            self.top_button_grid.options()))

        self.top_button_grid.contents = top_buttons

    def do_reset_to_defaults(self, sender):
        self.placement_controller.set_all_assignments(
            self.placement_controller.gen_defaults())

    def do_place_subordinate(self, sender, charm_class):
        sub_placeholder = self.placement_controller.sub_placeholder
        self.placement_controller.assign(sub_placeholder,
                                         charm_class,
                                         AssignmentType.BareMetal)
class AddServicesDialog(WidgetWrap):
    """ Dialog to add services. Does not specify placement.

    :param cb: callback routine to process submit/cancel actions
    """

    def __init__(self, install_controller, deploy_cb, cancel_cb):
        self.install_controller = install_controller
        self.orig_pc = install_controller.placement_controller
        self.pc = self.orig_pc.get_temp_copy()
        self.charms = []
        self.deploy_cb = deploy_cb
        self.cancel_cb = cancel_cb
        self.boxes = []
        w = self.build_widget()
        self.update()

        super().__init__(w)

    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 update(self):
        self.unrequired_undeployed_sl.update()
        self.deployed_sl.update()
        self.assigned_sl.update()
        self.update_buttons()

    def update_buttons(self):
        buttons = [(AttrMap(Button("Cancel", self.handle_cancel),
                            'button_primary', 'button_primary focus'),
                    self.button_grid.options())]
        n_assigned = len(self.pc.assigned_services)
        if n_assigned > 0 and self.pc.can_deploy():
            b = AttrMap(Button("Deploy", self.handle_deploy),
                        'button_primary', 'button_primary focus')
        else:
            b = AttrMap(SelectableIcon("(Deploy)"),
                        'disabled_button',
                        'disabled_button_focus')
        buttons.append((b, self.button_grid.options()))
        self.button_grid.contents = buttons

    def do_add(self, sender, charm_class):
        """Add the selected charm using default juju location.
        Equivalent to a simple 'juju deploy foo'

        Attempt to also add any charms that are required as a result
        of the newly added charm.
        """

        def num_to_auto_add(charm_class):
            return (charm_class.required_num_units() -
                    self.pc.assignment_machine_count_for_charm(charm_class))

        for i in range(max(1, num_to_auto_add(charm_class))):
            self.pc.assign(self.pc.def_placeholder, charm_class,
                           AssignmentType.DEFAULT)

        def get_unassigned_requireds():
            return [cc for cc in
                    self.pc.unassigned_undeployed_services()
                    if self.pc.get_charm_state(cc)[0] ==
                    CharmState.REQUIRED]

        while len(get_unassigned_requireds()) > 0:
            for u_r_cc in get_unassigned_requireds():
                for i in range(num_to_auto_add(u_r_cc)):
                    self.pc.assign(self.pc.def_placeholder, u_r_cc,
                                   AssignmentType.DEFAULT)
        self.update()

    def do_remove(self, sender, charm_class):
        "Undo an assignment"
        self.pc.remove_one_assignment(self.pc.def_placeholder,
                                      charm_class)
        self.update()

    def handle_deploy(self, button):
        """Commits changes to the main placement controller, and calls the
        deploy callback to do the rest.
        """
        self.orig_pc.update_from_controller(self.pc)
        self.deploy_cb()

    def handle_cancel(self, button):
        self.cancel_cb()
class ServiceChooser(WidgetWrap):

    """Presents list of services to put on a machine.

    Supports multiple selection, implying separate containers using
    --to.

    """

    def __init__(self, controller, machine, parent_widget):
        """
        controller is a PlacementController
        machine is the machine to show Services for
        parent_widget should support 'remove_overlay()'
        """
        self.controller = controller
        self.machine = machine
        self.parent_widget = parent_widget
        w = self.build_widgets()
        super().__init__(w)

    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 update(self):
        self.machine_widget.update()
        self.services_list.update()

    def do_add(self, sender, charm_class, atype):
        self.controller.assign(self.machine, charm_class, atype)
        self.update()

    def do_remove(self, sender, charm_class):
        self.controller.remove_one_assignment(self.machine, charm_class)
        self.update()

    def close_pressed(self, sender):
        self.parent_widget.remove_overlay(self)