def build_unselected_widgets(self):
        cdict = juju.constraints_to_dict(self.md.get('constraints', ''))

        label = str(self.juju_machine_id)
        self.juju_machine_id_button = SecondaryButton(label,
                                                      self.show_pin_chooser)
        self.juju_machine_id_label = Text(label)
        self.cores_field = IntEdit('', str(cdict.get('cores', '')))
        connect_signal(self.cores_field, 'change', self.handle_cores_changed)
        memval = cdict.get('mem', '')
        if memval != '':
            memval = self._format_constraint(memval) / 1024
        self.mem_field = Edit('', str(memval))
        connect_signal(self.mem_field, 'change', self.handle_mem_changed)
        diskval = cdict.get('root-disk', '')
        if diskval != '':
            diskval = self._format_constraint(diskval) / 1024
        self.disk_field = Edit('', str(diskval))
        connect_signal(self.disk_field, 'change', self.handle_disk_changed)

        if self.show_pin:
            machine_id_w = self.juju_machine_id_button
        else:
            machine_id_w = self.juju_machine_id_label
        cols = [machine_id_w]
        for field in (self.cores_field, self.mem_field, self.disk_field):
            cols.append(AttrMap(field, 'string_input', 'string_input_focus'))
        cols.append(Text("placeholder"))
        self.unselected_columns = Columns(cols, dividechars=2)
        self.update_assignments()
        return self.unselected_columns
    def update_action_buttons(self):

        all_actions = [(AssignmentType.BareMetal, 'Add as Bare Metal',
                        self.select_baremetal),
                       (AssignmentType.LXD, 'Add as LXD', self.select_lxd),
                       (AssignmentType.KVM, 'Add as KVM', self.select_kvm)]

        sc = self.application
        if sc:
            allowed_set = set(sc.allowed_assignment_types)
            allowed_types = set([atype for atype, _, _ in all_actions])
            allowed_types = allowed_types.intersection(allowed_set)
        else:
            allowed_types = set()

        # + 1 for the cancel button:
        if len(self.action_buttons) == len(allowed_types) + 1:
            return

        self.action_buttons = [
            SecondaryButton(label, func) for atype, label, func in all_actions
            if atype in allowed_types
        ]
        self.action_buttons.append(SecondaryButton("Cancel", self.do_cancel))

        opts = self.action_button_cols.options()
        self.action_button_cols.contents = [(b, opts)
                                            for b in self.action_buttons]
Exemplo n.º 3
0
    async def _build_widget(self):
        ws = []
        if not self.application.is_subordinate:
            ws.append(OptionWidget("Units", "int",
                                   "How many units to deploy.",
                                   self.application.num_units,
                                   current_value=self.num_units_copy,
                                   value_changed_callback=self.handle_scale))

        constraints_ow = OptionWidget(
            "Constraints", "string",
            "Set constraints on the application, ie. cores=4 mem=4G.",
            self.application.constraints,
            current_value=self.constraints_copy,
            value_changed_callback=self.handle_constraints)
        ws.append(constraints_ow)
        ws.append(self.constraints_error_label)

        ws += await self.get_whitelisted_option_widgets()
        self.toggle_show_all_button_index = len(ws) + 1
        self.toggle_show_all_button = SecondaryButton(
            "Show Advanced Configuration",
            lambda sender: app.loop.create_task(
                self.do_toggle_show_all_config()))
        if await self.get_non_whitelisted_option_widgets():
            ws += [HR(),
                   Columns([('weight', 1, Text(" ")),
                            (36, self.toggle_show_all_button)])]
        for widget in ws:
            self.widget.contents.append((widget,
                                         self.widget.options()))
Exemplo n.º 4
0
    def build_widgets(self, title_widgets):
        if title_widgets is None:
            title_widgets = [Text("Machines", align='center')]

        self.filter_edit_box = FilterBox(self.handle_filter_change)

        header_widgets = title_widgets + [Divider()]

        if self.show_filter_box:
            header_widgets += [self.filter_edit_box, Divider()]
        labels = ["ID", "Cores", "Memory (GiB)", "Storage (GiB)"]
        if self.show_assignments:
            labels += ["Assignments", ""]
        else:
            labels += [""]

        header_label_col = Columns([Text(m) for m in labels],
                                   dividechars=2)
        header_widgets.append(header_label_col)
        self.header_padding = len(header_widgets)
        self.add_new_button = SecondaryButton("Add New Machine",
                                              self.do_add_machine)
        self.add_new_cols = Columns([Text(s) for s in
                                     [' ', ' ', ' ', ' ', ' ']] +
                                    [self.add_new_button], dividechars=2)
        self.machine_pile = Pile(header_widgets + self.machine_widgets +
                                 [self.add_new_cols])
        return self.machine_pile
Exemplo n.º 5
0
    def build_widgets(self):
        m = self.machine
        l = ['{:20s}'.format(m.hostname),
             '{:3d}'.format(m.cpu_cores),
             '{:6s}'.format(m.mem),
             '{:10s}'.format(m.storage)]

        self.select_button_label = "Pin {} to {}".format(m.hostname,
                                                         self.target_info)
        self.unselect_button_label = "Un-pin {} from ".format(
            m.hostname) + "{}"

        self.select_button = SecondaryButton(self.select_button_label,
                                             self.handle_button)
        cols = [Text(m) for m in l]
        cols += [self.select_button]

        self.columns = Columns(cols)
        return self.columns
Exemplo n.º 6
0
 def build_widget(self):
     ws = []
     num_unit_ow = OptionWidget("Units",
                                "int",
                                "How many units to deploy.",
                                self.application.orig_num_units,
                                current_value=self.num_units_copy,
                                value_changed_callback=self.handle_scale)
     ws.append(num_unit_ow)
     ws += self.get_whitelisted_option_widgets()
     self.toggle_show_all_button_index = len(ws) + 1
     self.toggle_show_all_button = SecondaryButton(
         "Show Advanced Configuration", self.do_toggle_show_all_config)
     ws += [
         HR(),
         Columns([('weight', 1, Text(" ")),
                  (36, self.toggle_show_all_button)])
     ]
     return ws
Exemplo n.º 7
0
    def build_widgets(self, maxlen):
        num_str = "{}".format(self.application.num_units)
        col_pad = 6
        self.unit_w = Text('Units: {:4d}'.format(self.application.num_units),
                           align='right')
        cws = [
            (maxlen + col_pad, Text(self.application.service_name)),
            (10 + len(num_str), self.unit_w),
            ('weight', 1, Text(" ")),  # placeholder for instance type
            ('weight', 1, Text(" ")),  # placeholder for configure button
            ('weight', 1, Text(" ")),  # placeholder for architecture button
            (20, SubmitButton("Deploy", self._cb('deploy'))),
        ]
        if not self.hide_config:
            cws[3] = (20, SecondaryButton("Configure", self._cb('config')))

        if self.application.num_units > 0:
            cws[4] = (20, SecondaryButton("Architect", self._cb('arch')))

        self.columns = Columns(cws, dividechars=1)
        return self.columns
Exemplo n.º 8
0
    def build_widgets(self, maxlen):
        num_str = "{}".format(self.application.num_units)
        col_pad = 6
        self.unit_w = Text('', align='right')
        self.update_units()
        cws = [
            (maxlen + col_pad, Text(self.application.name)),
            (10 + len(num_str), self.unit_w),
            ('weight', 1, Text(" ")),  # placeholder for instance type
            (20, SecondaryButton("Configure", self._cb('config'))),
        ]

        self.columns = Columns(cws, dividechars=1)
        return self.columns
Exemplo n.º 9
0
    def build_widgets(self):
        desc_text = Text(["\n", strip_solo_dots(self.description)])

        self.reset_button = SecondaryButton("Reset to Default", self.do_reset)
        if self.optype == OptionType.BOOLEAN:
            self.control = CheckBox('', state=bool(self.current_value))
            self.wrapped_control = self.control
        elif self.optype == OptionType.INT:
            self.control = IntEdit(default=self.current_value)
            self.wrapped_control = Color.string_input(
                self.control, focus_map='string_input focus')
        elif self.optype == OptionType.STRING:
            edit_text = self.current_value or ""
            self.control = StringEditor(edit_text=edit_text)
            self.wrapped_control = Color.string_input(
                self.control, focus_map='string_input focus')
        elif self.optype == OptionType.FLOAT:
            edit_text = str(self.current_value)
            self.control = StringEditor(edit_text=edit_text)
            self.wrapped_control = Color.string_input(
                self.control, focus_map='string_input focus')
        else:
            raise Exception("Unknown option type")

        self.control_columns = Columns(
            [('pack', Text("{}:".format(self.name), align='right')),
             (80, self.wrapped_control)],
            dividechars=1)

        if self.optype in [OptionType.STRING, OptionType.FLOAT]:
            connect_signal(self.control._edit, 'change',
                           self.handle_value_changed)
        else:
            connect_signal(self.control, 'change', self.handle_value_changed)

        button_grid = GridFlow([self.reset_button], 36, 1, 0, 'right')

        return Pile([
            Padding.line_break(""),
            Padding.left(self.control_columns, left=1),
            Padding.left(desc_text, left=2), button_grid
        ])
Exemplo n.º 10
0
    def update_assignments(self):
        assignments = []

        mps = self.controller.get_all_assignments(self.juju_machine_id)
        if len(mps) > 0:
            if self.show_assignments:
                ad = defaultdict(list)
                for application, atype in mps:
                    ad[atype].append(application)
                astr = " ".join([
                    "{}{}".format(
                        atype_to_label([atype])[0], ",".join(
                            [application.service_name for application in al]))
                    for atype, al in ad.items()
                ])
                assignments.append(astr)
        else:
            if self.show_assignments:
                assignments.append("-")

        if any([application == self.application for application, _ in mps]):
            action = self.do_remove
            label = "Remove"
        else:
            action = self.do_select
            label = "Select"

        self.select_button = SecondaryButton(label, action)

        cols = [Text(s) for s in assignments]

        current_assignments = [a for a, _ in mps if a == self.application]
        if self.all_assigned and len(current_assignments) == 0:
            cols.append(Text(""))
        else:
            cols.append(self.select_button)
        opts = self.unselected_columns.options()
        self.unselected_columns.contents[4:] = [(w, opts) for w in cols]
Exemplo n.º 11
0
class MachineWidget(ContainerWidgetWrap):

    """A widget displaying a machine and one action button.

    machine - the machine to display

    select_cb - a function that takes a machine to select

    unselect_cb - a function that takes a machine to un-select

    target_info - a string describing what we're pinning to

    current_pin_cb - a function that takes a machine and returns a
    string if it's already pinned or None if it is not

    """

    def __init__(self, machine, select_cb, unselect_cb,
                 target_info, current_pin_cb):
        self.machine = machine
        self.select_cb = select_cb
        self.unselect_cb = unselect_cb
        self.target_info = target_info
        self.current_pin_cb = current_pin_cb

        w = self.build_widgets()
        super().__init__(w)
        self.update()

    def selectable(self):
        return True

    def build_widgets(self):
        m = self.machine
        l = ['{:20s}'.format(m.hostname),
             '{:3d}'.format(m.cpu_cores),
             '{:6s}'.format(m.mem),
             '{:10s}'.format(m.storage)]

        self.select_button_label = "Pin {} to {}".format(m.hostname,
                                                         self.target_info)
        self.unselect_button_label = "Un-pin {} from ".format(
            m.hostname) + "{}"

        self.select_button = SecondaryButton(self.select_button_label,
                                             self.handle_button)
        cols = [Text(m) for m in l]
        cols += [self.select_button]

        self.columns = Columns(cols)
        return self.columns

    def update_machine(self):
        """Refresh with potentially updated machine info from controller.
        Assumes that machine exists - machines going away is handled
        in machineslist.update().
        """
        machines = app.maas.client.get_machines()
        if machines is None:
            return
        self.machine = next((m for m in machines
                             if m.instance_id == self.machine.instance_id),
                            None)

    def __repr__(self):
        return "<MachineWidget for {}>".format(self.machine)

    def update(self):
        self.update_machine()
        current_pin = self.current_pin_cb(self.machine)
        if current_pin:
            l = self.unselect_button_label.format(current_pin)
            self.select_button.set_label(l)
        else:
            self.select_button.set_label(self.select_button_label)

    def handle_button(self, sender):
        if self.current_pin_cb(self.machine):
            self.unselect_cb(self.machine)
        else:
            self.select_cb(self.machine)

        self.update()
Exemplo n.º 12
0
class JujuMachineWidget(ContainerWidgetWrap):
    """A widget displaying a machine and action buttons.

    juju_machine_id = juju id of the machine

    md = the machine dict

    application - the current application for which machines are being shown

    assign_cb - a function that takes a machine and assignmenttype to
    perform the button action

    unassign_cb - a function that takes a machine and removes
    assignments for the machine

    controller - a controller object that provides show_pin_chooser

    show_assignments - display info about which charms are assigned
    and what assignment type (LXC, KVM, etc) they have.

    show_pin - show button to pin juju machine to a maas machine

    """
    def __init__(self,
                 juju_machine_id,
                 md,
                 application,
                 assign_cb,
                 unassign_cb,
                 controller,
                 show_assignments=True,
                 show_pin=False):
        self.juju_machine_id = juju_machine_id
        self.md = md
        self.application = application
        self.is_selected = False
        self.assign_cb = assign_cb
        self.unassign_cb = unassign_cb
        self.controller = controller
        self.show_assignments = show_assignments
        self.show_pin = show_pin
        self.all_assigned = False

        w = self.build_widgets()
        super().__init__(w)
        self.update()

    def selectable(self):
        return True

    def __repr__(self):
        return "jujumachinewidget #" + str(self.juju_machine_id)

    def build_widgets(self):

        self.action_button_cols = Columns([])
        self.action_buttons = []
        self.build_unselected_widgets()
        self.pile = Pile([self.unselected_columns])
        return self.pile

    def build_unselected_widgets(self):
        cdict = juju.constraints_to_dict(self.md.get('constraints', ''))

        label = str(self.juju_machine_id)
        self.juju_machine_id_button = SecondaryButton(label,
                                                      self.show_pin_chooser)
        self.juju_machine_id_label = Text(label)
        self.cores_field = IntEdit('', str(cdict.get('cores', '')))
        connect_signal(self.cores_field, 'change', self.handle_cores_changed)
        memval = cdict.get('mem', '')
        if memval != '':
            memval = self._format_constraint(memval) / 1024
        self.mem_field = Edit('', str(memval))
        connect_signal(self.mem_field, 'change', self.handle_mem_changed)
        diskval = cdict.get('root-disk', '')
        if diskval != '':
            diskval = self._format_constraint(diskval) / 1024
        self.disk_field = Edit('', str(diskval))
        connect_signal(self.disk_field, 'change', self.handle_disk_changed)

        if self.show_pin:
            machine_id_w = self.juju_machine_id_button
        else:
            machine_id_w = self.juju_machine_id_label
        cols = [machine_id_w]
        for field in (self.cores_field, self.mem_field, self.disk_field):
            cols.append(AttrMap(field, 'string_input', 'string_input_focus'))
        cols.append(Text("placeholder"))
        self.unselected_columns = Columns(cols, dividechars=2)
        self.update_assignments()
        return self.unselected_columns

    def update_assignments(self):
        assignments = []

        mps = self.controller.get_all_assignments(self.juju_machine_id)
        if len(mps) > 0:
            if self.show_assignments:
                ad = defaultdict(list)
                for application, atype in mps:
                    ad[atype].append(application)
                astr = " ".join([
                    "{}{}".format(
                        atype_to_label([atype])[0], ",".join(
                            [application.service_name for application in al]))
                    for atype, al in ad.items()
                ])
                assignments.append(astr)
        else:
            if self.show_assignments:
                assignments.append("-")

        if any([application == self.application for application, _ in mps]):
            action = self.do_remove
            label = "Remove"
        else:
            action = self.do_select
            label = "Select"

        self.select_button = SecondaryButton(label, action)

        cols = [Text(s) for s in assignments]

        current_assignments = [a for a, _ in mps if a == self.application]
        if self.all_assigned and len(current_assignments) == 0:
            cols.append(Text(""))
        else:
            cols.append(self.select_button)
        opts = self.unselected_columns.options()
        self.unselected_columns.contents[4:] = [(w, opts) for w in cols]

    def update(self):
        self.update_action_buttons()

        if self.is_selected:
            self.update_selected()
        else:
            self.update_unselected()

    def update_selected(self):
        cn = self.application.service_name
        msg = Text("  Add {} to machine #{}:".format(cn, self.juju_machine_id))
        self.pile.contents = [(msg, self.pile.options()),
                              (self.action_button_cols, self.pile.options()),
                              (Divider(), self.pile.options())]

    def update_unselected(self):
        if self.show_pin:
            pinned_machine = self.controller.get_pin(self.juju_machine_id)

            if pinned_machine:
                label = "{} \N{RIGHTWARDS ARROW}  {}".format(
                    self.juju_machine_id, pinned_machine.hostname)
            else:
                label = str(self.juju_machine_id)
            label = "\N{PENCIL}  {}".format(label)
            self.juju_machine_id_button.set_label(label)
        else:
            self.juju_machine_id_label.set_text(str(self.juju_machine_id))

        self.pile.contents = [(self.unselected_columns, self.pile.options()),
                              (Divider(), self.pile.options())]
        self.update_assignments()

    def update_action_buttons(self):

        all_actions = [(AssignmentType.BareMetal, 'Add as Bare Metal',
                        self.select_baremetal),
                       (AssignmentType.LXD, 'Add as LXD', self.select_lxd),
                       (AssignmentType.KVM, 'Add as KVM', self.select_kvm)]

        sc = self.application
        if sc:
            allowed_set = set(sc.allowed_assignment_types)
            allowed_types = set([atype for atype, _, _ in all_actions])
            allowed_types = allowed_types.intersection(allowed_set)
        else:
            allowed_types = set()

        # + 1 for the cancel button:
        if len(self.action_buttons) == len(allowed_types) + 1:
            return

        self.action_buttons = [
            SecondaryButton(label, func) for atype, label, func in all_actions
            if atype in allowed_types
        ]
        self.action_buttons.append(SecondaryButton("Cancel", self.do_cancel))

        opts = self.action_button_cols.options()
        self.action_button_cols.contents = [(b, opts)
                                            for b in self.action_buttons]

    def do_select(self, sender):
        self.is_selected = True
        self.update()
        self.pile.focus_position = 1
        self.action_button_cols.focus_position = 0

    def do_remove(self, sender):
        self.unassign_cb(self.juju_machine_id)

    def do_cancel(self, sender):
        self.is_selected = False
        self.update()
        self.pile.focus_position = 0

    def _do_select_assignment(self, atype):
        self.assign_cb(self.juju_machine_id, atype)
        self.pile.focus_position = 0
        self.is_selected = False
        self.update()

    def select_baremetal(self, sender):
        self._do_select_assignment(AssignmentType.BareMetal)

    def select_lxd(self, sender):
        self._do_select_assignment(AssignmentType.LXD)

    def select_kvm(self, sender):
        self._do_select_assignment(AssignmentType.KVM)

    def handle_cores_changed(self, sender, val):
        if val == '':
            self.md = self.controller.clear_constraint(self.juju_machine_id,
                                                       'cores')
        else:
            self.md = self.controller.set_constraint(self.juju_machine_id,
                                                     'cores', val)

    def _format_constraint(self, val):
        "Store constraints as int values of megabytes"
        if val.isnumeric():
            return int(val) * 1024
        else:
            return units.human_to_mb(val)

    def handle_mem_changed(self, sender, val):
        if val == '':
            self.md = self.controller.clear_constraint(self.juju_machine_id,
                                                       'mem')
        else:
            try:
                self.md = self.controller.set_constraint(
                    self.juju_machine_id, 'mem', self._format_constraint(val))
            except ValueError:
                return

    def handle_disk_changed(self, sender, val):
        if val == '':
            self.md = self.controller.clear_constraint(self.juju_machine_id,
                                                       'root-disk')
        else:
            try:
                self.md = self.controller.set_constraint(
                    self.juju_machine_id, 'root-disk',
                    self._format_constraint(val))
            except ValueError:
                return

    def show_pin_chooser(self, sender):
        self.controller.show_pin_chooser(self.juju_machine_id)
Exemplo n.º 13
0
class ApplicationConfigureView(BaseView):
    metrics_title = 'Configure Application'

    def __init__(self, application, close_cb):
        self.title = "Configure {}".format(application.name)
        self.application = application
        self.prev_screen = close_cb
        self.options_copy = self.application.options.copy()
        self.num_units_copy = self.application.num_units
        self.constraints_copy = self.application.constraints
        self.constraints_error_label = Text(('body', ''))
        self.showing_all = False
        super().__init__()

    def set_constraints_error(self, msg=None):
        if not msg:
            msg = (
                "Invalid constraints given, your choices are '{}'".format(
                    ", ".join(consts.ALLOWED_CONSTRAINTS)))
        self.constraints_error_label.set_text(('error_major', msg))

    def clear_constraints_error(self):
        self.constraints_error_label.set_text(('body', ''))

    def build_widget(self):
        app.loop.create_task(self._build_widget())
        return []

    async def _build_widget(self):
        ws = []
        if not self.application.is_subordinate:
            ws.append(OptionWidget("Units", "int",
                                   "How many units to deploy.",
                                   self.application.num_units,
                                   current_value=self.num_units_copy,
                                   value_changed_callback=self.handle_scale))

        constraints_ow = OptionWidget(
            "Constraints", "string",
            "Set constraints on the application, ie. cores=4 mem=4G.",
            self.application.constraints,
            current_value=self.constraints_copy,
            value_changed_callback=self.handle_constraints)
        ws.append(constraints_ow)
        ws.append(self.constraints_error_label)

        ws += await self.get_whitelisted_option_widgets()
        self.toggle_show_all_button_index = len(ws) + 1
        self.toggle_show_all_button = SecondaryButton(
            "Show Advanced Configuration",
            lambda sender: app.loop.create_task(
                self.do_toggle_show_all_config()))
        if await self.get_non_whitelisted_option_widgets():
            ws += [HR(),
                   Columns([('weight', 1, Text(" ")),
                            (36, self.toggle_show_all_button)])]
        for widget in ws:
            self.widget.contents.append((widget,
                                         self.widget.options()))

    def build_buttons(self):
        return [self.button('APPLY CHANGES', self.submit)]

    async def get_whitelisted_option_widgets(self):
        options = await app.juju.charmstore.config(self.application.charm)

        svc_opts_whitelist = utils.get_options_whitelist(
            self.application.name)
        hidden = [n for n in options['Options'].keys()
                  if n not in svc_opts_whitelist]
        app.log.info("Hiding options not in the whitelist: {}".format(hidden))

        return self._get_option_widgets(svc_opts_whitelist, options['Options'])

    async def get_non_whitelisted_option_widgets(self):
        options = await app.juju.charmstore.config(self.application.charm)

        svc_opts_whitelist = utils.get_options_whitelist(
            self.application.name)
        hidden = [n for n in options['Options'].keys()
                  if n not in svc_opts_whitelist]
        return self._get_option_widgets(hidden, options['Options'])

    def _get_option_widgets(self, opnames, options):
        ws = []
        for opname in opnames:
            try:
                opdict = options[opname]
            except KeyError:
                app.log.debug(
                    "Unknown charm option ({}), skipping".format(opname))
                continue
            cv = self.application.options.get(opname, None)
            ow = OptionWidget(opname,
                              opdict['Type'],
                              opdict['Description'],
                              opdict['Default'],
                              current_value=cv,
                              value_changed_callback=self.handle_edit)
            ws.append(ow)
        return ws

    async def do_toggle_show_all_config(self):
        if not self.showing_all:
            new_ows = await self.get_non_whitelisted_option_widgets()
            header = Text("Advanced Configuration Options")
            opts = self.widget.options()
            self.widget.contents.append((header, opts))
            for ow in new_ows:
                self.widget.contents.append((ow, opts))
            self.toggle_show_all_button.set_label(
                "Hide Advanced Configuration")
            self.showing_all = True
        else:
            i = self.toggle_show_all_button_index
            self.widget.contents = self.widget.contents[:i + 1]
            self.toggle_show_all_button.set_label(
                "Show Advanced Configuration")
            self.showing_all = False

    def handle_edit(self, opname, value):
        self.options_copy[opname] = value

    def handle_scale(self, opname, scale):
        self.num_units_copy = scale

    def handle_constraints(self, opname, constraint):
        self.constraints_copy = constraint

    def submit(self):
        if self.constraints_copy:
            try:
                parsed = set(parse_constraints(self.constraints_copy))
            except ValueError:
                return self.set_constraints_error()
            has_valid_constraints = parsed.issubset(
                {normalize_key(field) for field in consts.ALLOWED_CONSTRAINTS})
            if not has_valid_constraints:
                return self.set_constraints_error()

        self.application.options = self.options_copy
        self.application.num_units = self.num_units_copy
        self.application.constraints = self.constraints_copy
        # Apply fragment updates to bundle
        app.current_bundle.apply({"applications": {
            self.application.name: self.application.to_dict()
        }})

        self.prev_screen()
Exemplo n.º 14
0
class ApplicationConfigureView(BaseView):
    def __init__(self, application, close_cb):
        self.title = "Configure {}".format(application.service_name)
        self.application = application
        self.prev_screen = close_cb
        self.options_copy = self.application.options.copy()
        self.num_units_copy = self.application.num_units
        self.showing_all = False
        super().__init__()

    def build_widget(self):
        ws = []
        num_unit_ow = OptionWidget("Units",
                                   "int",
                                   "How many units to deploy.",
                                   self.application.orig_num_units,
                                   current_value=self.num_units_copy,
                                   value_changed_callback=self.handle_scale)
        ws.append(num_unit_ow)
        ws += self.get_whitelisted_option_widgets()
        self.toggle_show_all_button_index = len(ws) + 1
        self.toggle_show_all_button = SecondaryButton(
            "Show Advanced Configuration", self.do_toggle_show_all_config)
        ws += [
            HR(),
            Columns([('weight', 1, Text(" ")),
                     (36, self.toggle_show_all_button)])
        ]
        return ws

    def build_buttons(self):
        return [self.button('APPLY CHANGES', self.submit)]

    def get_whitelisted_option_widgets(self):
        service_id = self.application.csid.as_str_without_rev()
        options = app.metadata_controller.get_options(service_id)

        svc_opts_whitelist = utils.get_options_whitelist(
            self.application.service_name)
        hidden = [n for n in options.keys() if n not in svc_opts_whitelist]
        app.log.info("Hiding options not in the whitelist: {}".format(hidden))

        return self._get_option_widgets(svc_opts_whitelist, options)

    def get_non_whitelisted_option_widgets(self):
        service_id = self.application.csid.as_str_without_rev()
        options = app.metadata_controller.get_options(service_id)

        svc_opts_whitelist = utils.get_options_whitelist(
            self.application.service_name)
        hidden = [n for n in options.keys() if n not in svc_opts_whitelist]
        return self._get_option_widgets(hidden, options)

    def _get_option_widgets(self, opnames, options):
        ws = []
        for opname in opnames:
            try:
                opdict = options[opname]
            except KeyError:
                app.log.debug(
                    "Unknown charm option ({}), skipping".format(opname))
                continue
            cv = self.application.options.get(opname, None)
            ow = OptionWidget(opname,
                              opdict['Type'],
                              opdict['Description'],
                              opdict['Default'],
                              current_value=cv,
                              value_changed_callback=self.handle_edit)
            ws.append(ow)
        return ws

    def do_toggle_show_all_config(self, sender):
        if not self.showing_all:
            new_ows = self.get_non_whitelisted_option_widgets()
            header = Text("Advanced Configuration Options")
            opts = self.widget.options()
            self.widget.contents.append((header, opts))
            for ow in new_ows:
                self.widget.contents.append((ow, opts))
            self.toggle_show_all_button.set_label(
                "Hide Advanced Configuration")
            self.showing_all = True
        else:
            i = self.toggle_show_all_button_index
            self.widget.contents = self.widget.contents[:i + 1]
            self.toggle_show_all_button.set_label(
                "Show Advanced Configuration")
            self.showing_all = False

    def handle_edit(self, opname, value):
        self.options_copy[opname] = value

    def handle_scale(self, opname, scale):
        self.num_units_copy = scale

    def submit(self):
        self.application.options = self.options_copy
        self.application.num_units = self.num_units_copy
        self.prev_screen()