From: Andy Bavier Date: Thu, 3 Jun 2010 14:00:12 +0000 (-0400) Subject: Added Node selection and Sliver (attribute) configuration panels to X-Git-Url: http://git.onelab.eu/?p=sfa-gui.git;a=commitdiff_plain;h=7ce5cc20aaa8c2504abff63921268c0f6fa8a676 Added Node selection and Sliver (attribute) configuration panels to PlanetLab and VINI. --- diff --git a/LinkPanel.py b/LinkPanel.py new file mode 100644 index 0000000..cc36bc3 --- /dev/null +++ b/LinkPanel.py @@ -0,0 +1,80 @@ +from pyjamas.ui.VerticalPanel import VerticalPanel +from pyjamas.ui.HorizontalPanel import HorizontalPanel +from pyjamas.ui.CaptionPanel import CaptionPanel +from pyjamas.ui.ListBox import ListBox +from pyjamas.ui.TextBox import TextBox +from pyjamas.ui.Button import Button +from pyjamas.ui.HTML import HTML +from pyjamas.ui import HasAlignment + +class AddPanel(CaptionPanel): + def __init__(self, top): + CaptionPanel.__init__(self, "Add virtual link") + self.top = top + + hp = HorizontalPanel() + self.end1 = ListBox() + self.end1.addItem("Endpoint 1") + for sliver in self.top.rspec.get_sliver_list(): + self.end1.addItem(sliver) + + self.end2 = ListBox() + self.end2.addItem("Endpoint 2") + for sliver in self.top.rspec.get_sliver_list(): + self.end2.addItem(sliver) + + self.bw = TextBox() + self.bw.setText("1000") + + hp.add(self.end1) + hp.add(self.end2) + hp.add(self.bw) + hp.add(Button("Add", self.go)) + + self.add(hp) + + def go(self, sender): + end1 = self.end1.getItemText(self.end1.getSelectedIndex()) + end2 = self.end2.getItemText(self.end2.getSelectedIndex()) + bw = self.bw.getText() + + self.top.refresh() + + +class VlinkPanel(HorizontalPanel): + def __init__(self, top, description, bw): + HorizontalPanel.__init__(self) + self.description = description + self.bw = bw + self.top = top + + self.setSpacing(5) + self.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE) + b = Button("X", self.delete) + self.add(b) + self.add(HTML("%s (%s kbps)" % (self.description, self.bw))) + + def delete(self, sender): + self.top.refresh() + + +class LinkPanel(VerticalPanel): + def __init__(self, sfadata, rspec): + VerticalPanel.__init__(self) + self.data = sfadata + self.rspec = rspec + + self.refresh() + + def refresh(self): + self.clear() + self.add(AddPanel(self)) + + cp = CaptionPanel("Virtual links") + vp = VerticalPanel() + vlinks = self.rspec.get_vlink_list() + for (desc, bw) in vlinks: + vp.add(VlinkPanel(self, desc, bw)) + cp.add(vp) + self.add(cp) + diff --git a/NodePanel.py b/NodePanel.py new file mode 100644 index 0000000..b7333ba --- /dev/null +++ b/NodePanel.py @@ -0,0 +1,120 @@ +from pyjamas.ui.HorizontalPanel import HorizontalPanel +from pyjamas.ui.VerticalPanel import VerticalPanel +from pyjamas.ui.DockPanel import DockPanel +from pyjamas.ui.CaptionPanel import CaptionPanel +from pyjamas.ui.Button import Button +from pyjamas.ui.Composite import Composite +from pyjamas.ui.ListBox import ListBox +from pyjamas.ui.TextBox import TextBox +from pyjamas.ui.HTML import HTML +from pyjamas.ui import HasAlignment +import re + +def faster_clear(self): + count = self.getItemCount() + while count > 0: + self.removeItem(0) + count -= 1 +ListBox.clear = faster_clear + +class NodePanel(DockPanel): + def __init__(self, sfadata, rspec): + DockPanel.__init__(self) + self.data = sfadata + self.rspec = rspec + + self.setSize("100%", "100%") + self.setHorizontalAlignment(HasAlignment.ALIGN_CENTER) + self.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE) + self.regex = None + + leftpanel = VerticalPanel() + leftcap = CaptionPanel("Available nodes") + self.leftlist = ListBox(MultipleSelect=True, VisibleItemCount=20) + leftcap.add(self.leftlist) + leftpanel.add(leftcap) + + hp1 = HorizontalPanel() + filterButton = Button("Filter", self.filter) + self.regExBox = TextBox() + hp1.add(filterButton) + hp1.add(self.regExBox) + leftpanel.add(hp1) + + rightpanel = VerticalPanel() + rightcap = CaptionPanel("Selected nodes") + self.rightlist = ListBox(MultipleSelect=True, VisibleItemCount=20) + rightcap.add(self.rightlist) + rightpanel.add(rightcap) + + hp2 = HorizontalPanel() + applyButton = Button("Apply", self.apply) + resetButton = Button("Reset", self.reset) + hp2.add(applyButton) + hp2.add(resetButton) + rightpanel.add(hp2) + + addButton = Button(">>", self.addNodes) + removeButton = Button("<<", self.removeNodes) + vertpanel = VerticalPanel() + vertpanel.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE) + vertpanel.add(addButton) + vertpanel.add(removeButton) + + self.add(leftpanel, DockPanel.WEST) + self.add(rightpanel, DockPanel.EAST) + self.add(vertpanel, DockPanel.CENTER) + + self.refresh() + + def refresh(self): + slivers = self.sortNodes(self.rspec.get_sliver_list()) + all = self.rspec.get_node_list() + available = self.sortNodes(filter(lambda x:x not in slivers,all)) + if self.regex: + pattern = re.compile(self.regex) + available = filter(pattern.search, available) + self.leftlist.clear() + for i in available: + self.leftlist.addItem(i) + self.rightlist.clear() + for i in slivers: + self.rightlist.addItem(i) + + def onShow(self): + pass + + def sortNodes(self, nodes): + nodes.sort() + return nodes + + def getSelected(self, listbox): + got = [] + for i in range(listbox.getItemCount()): + if listbox.isItemSelected(i): + got.append(listbox.getItemText(i)) + return got + + def addNodes(self, sender): + nodes = self.getSelected(self.leftlist) + for node in nodes: + self.rspec.add_sliver(node) + self.refresh() + + def removeNodes(self, sender): + nodes = self.getSelected(self.rightlist) + for node in nodes: + self.rspec.remove_sliver(node) + self.refresh() + + def apply(self, sender): + # Call sfi.py create via ViniData object + pass + + def reset(self, sender): + self.rspec = self.data.getRSpec() + self.refresh() + + def filter(self, sender): + self.regex = self.regExBox.getText() + self.refresh() diff --git a/PlanetLab.py b/PlanetLab.py index 50407c7..6488da9 100644 --- a/PlanetLab.py +++ b/PlanetLab.py @@ -1,31 +1,42 @@ from Sink import Sink, SinkInfo +from pyjamas.ui.TabPanel import TabPanel from pyjamas.ui.VerticalPanel import VerticalPanel from pyjamas.ui.TextArea import TextArea from pyjamas.ui.HTML import HTML from SfaData import PlanetLabData +from NodePanel import NodePanel +from LinkPanel import LinkPanel +from SliverPanel import SliverPanel -class PlanetLab(Sink): +class PlTabs(TabPanel): def __init__(self): + TabPanel.__init__(self) - Sink.__init__(self) - self.panel = VerticalPanel() - self.panel.setSize("100%", "100%") self.data = PlanetLabData() self.rspec = self.data.getRSpec() - # Just to show that we can retrieve the RSpec - ta = TextArea() - ta.setSize("100%", "100%") - ta.setText(self.rspec) - self.panel.add(ta) + nodetab = NodePanel(self.data, self.rspec) + slivertab = SliverPanel(self.data, self.rspec) + + self.add(nodetab, "Nodes") + self.add(slivertab, "Slivers") + self.selectTab(0) + + def onTabSelected(self, sender, index): + tab = self.getWidget(index) + tab.refresh() + TabPanel.onTabSelected(self, sender, index) - self.initWidget(self.panel) +class PlanetLab(Sink): + def __init__(self): - def onShow(self): - # Do we want to refresh the RSpec? - pass + Sink.__init__(self) + self.tabs = PlTabs() + self.tabs.setWidth("100%") + self.tabs.setHeight("100%") + self.initWidget(self.tabs) def init(): return SinkInfo("PlanetLab", "Specify PlanetLab Resources", PlanetLab) diff --git a/SfaData.py b/SfaData.py index a26aaf9..e1abfac 100644 --- a/SfaData.py +++ b/SfaData.py @@ -48,7 +48,7 @@ class ViniData(SfaData): def __init__(self): SfaData.__init__(self) self.registry = "http://www.planet-lab.org:12345" - self.slicemgr = "http://www.vini-veritas.net:12347" + self.slicemgr = "http://www.vini-veritas.net:12346" def getRSpec(self): xml = SfaData.getRSpec(self) @@ -58,11 +58,15 @@ class PlanetLabData(SfaData): def __init__(self): SfaData.__init__(self) self.registry = "http://www.planet-lab.org:12345" - self.slicemgr = "http://www.planet-lab.org:12347" + self.slicemgr = "http://www.planet-lab.org:12346" + + def getRSpec(self): + xml = SfaData.getRSpec(self) + return RSpec(xml) class OpenCirrusData(SfaData): def __init__(self): SfaData.__init__(self) self.registry = "http://www.planet-lab.org:12345" - self.slicemgr = "http://www.planet-lab.org:12347" + self.slicemgr = "http://www.planet-lab.org:12346" diff --git a/SliverPanel.py b/SliverPanel.py new file mode 100644 index 0000000..2ca4bbf --- /dev/null +++ b/SliverPanel.py @@ -0,0 +1,114 @@ +from pyjamas.ui.VerticalPanel import VerticalPanel +from pyjamas.ui.HorizontalPanel import HorizontalPanel +from pyjamas.ui.CaptionPanel import CaptionPanel +from pyjamas.ui.ListBox import ListBox +from pyjamas.ui.TextBox import TextBox +from pyjamas.ui.Button import Button +from pyjamas.ui.HTML import HTML +from pyjamas.ui import HasAlignment + +class AddPanel(CaptionPanel): + def __init__(self, top): + CaptionPanel.__init__(self, "Add attribute") + self.top = top + + hp = HorizontalPanel() + self.nodes = ListBox() + self.nodes.addItem("All nodes") + for sliver in self.top.rspec.get_sliver_list(): + self.nodes.addItem(sliver) + + self.attrs = ListBox() + # Hardcoded for now... + names = ['capabilities', 'codemux', 'cpu_pct', 'cpu_share', + 'delegations', 'disk_max', 'initscript', 'ip_addresses', + 'net_i2_max_kbyte', 'net_i2_max_rate', 'net_i2_min_rate', + 'net_i2_share', 'net_i2_thresh_kbyte', + 'net_max_kbyte', 'net_max_rate', 'net_min_rate', + 'net_share', 'net_thresh_kbyte', + 'vsys', 'vsys_vnet'] + for name in names: + self.attrs.addItem(name) + + self.value = TextBox() + + hp.add(self.attrs) + hp.add(self.value) + hp.add(self.nodes) + hp.add(Button("Add", self.go)) + + self.add(hp) + + def go(self, sender): + name = self.attrs.getItemText(self.attrs.getSelectedIndex()) + value = self.value.getText() + nodeindex = self.nodes.getSelectedIndex() + if nodeindex == 0: + self.top.rspec.add_default_sliver_attribute(name, value) + else: + node = self.nodes.getItemText(nodeindex) + self.top.rspec.add_sliver_attribute(node, name, value) + self.top.refresh() + + +class AttributePanel(HorizontalPanel): + def __init__(self, top, name, value, node=None): + HorizontalPanel.__init__(self) + self.name = name + self.value = value + self.node = node + self.top = top + + self.setSpacing(5) + self.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE) + if not node: + b = Button("X", self.delete_all) + else: + b = Button("X", self.delete) + self.add(b) + self.add(HTML("%s: %s" % (self.name, self.value))) + + def delete_all(self, sender): + self.top.rspec.remove_default_sliver_attribute(self.name, self.value) + self.top.refresh() + + def delete(self, sender): + self.top.rspec.remove_sliver_attribute(self.node, self.name, self.value) + self.top.refresh() + + +class SliverPanel(VerticalPanel): + def __init__(self, sfadata, rspec): + VerticalPanel.__init__(self) + self.data = sfadata + self.rspec = rspec + self.refresh() + + def refresh(self): + self.clear() + self.add(AddPanel(self)) + + allattrs = self.rspec.get_default_sliver_attributes() + attrdict = {} + slivers = self.rspec.get_sliver_list() + for sliver in slivers: + attrs = self.rspec.get_sliver_attributes(sliver) + attrdict[sliver] = attrs + + if allattrs: + cp = CaptionPanel("All nodes") + vp = VerticalPanel() + for (name, value) in allattrs: + ap = AttributePanel(self, name, value) + vp.add(ap) + cp.add(vp) + self.add(cp) + + for sliver in slivers: + if attrdict[sliver]: + cp = CaptionPanel(sliver) + for (name, value) in attrdict[sliver]: + ap = AttributePanel(self, name, value, sliver) + cp.add(ap) + self.add(cp) + diff --git a/VINI.py b/VINI.py index c82c7fd..15f5795 100644 --- a/VINI.py +++ b/VINI.py @@ -1,46 +1,42 @@ from Sink import Sink, SinkInfo -from pyjamas.ui.horizsplitpanel import HorizontalSplitPanel -from pyjamas.ui.CaptionPanel import CaptionPanel -from pyjamas.ui.ListBox import ListBox -from pyjamas.ui.HTML import HTML +from pyjamas.ui.TabPanel import TabPanel +from pyjamas.ui.VerticalPanel import VerticalPanel from SfaData import ViniData +from NodePanel import NodePanel +from LinkPanel import LinkPanel +from SliverPanel import SliverPanel -class VINI(Sink): +class VINITabs(TabPanel): def __init__(self): + TabPanel.__init__(self) - Sink.__init__(self) - self.panel = HorizontalSplitPanel() - self.panel.setSize("100%", "100%") - self.panel.setSplitPosition("50%") self.data = ViniData() self.rspec = self.data.getRSpec() - leftcap = CaptionPanel("Available nodes") - leftcap.setSize("90%", "90%") - leftlist = ListBox(MultipleSelect=True) - leftlist.setSize("100%", "100%") - available = self.rspec.get_node_list() - for i in available: - leftlist.addItem(i) - leftcap.add(leftlist) - - rightcap = CaptionPanel("Selected nodes") - rightcap.setSize("90%", "90%") - rightlist = ListBox(MultipleSelect=True) - rightlist.setSize("100%", "100%") - slivers = self.rspec.get_sliver_list() - for i in slivers: - rightlist.addItem(i) - rightcap.add(rightlist) + nodetab = NodePanel(self.data, self.rspec) + linktab = LinkPanel(self.data, self.rspec) + slivertab = SliverPanel(self.data, self.rspec) + + self.add(nodetab, "Nodes") + self.add(linktab, "Links") + self.add(slivertab, "Slivers") + self.selectTab(0) - self.panel.setLeftWidget(leftcap) - self.panel.setRightWidget(rightcap) + def onTabSelected(self, sender, index): + tab = self.getWidget(index) + tab.refresh() + TabPanel.onTabSelected(self, sender, index) - self.initWidget(self.panel) +class VINI(Sink): + def __init__(self): - def onShow(self): - pass + Sink.__init__(self) + + self.tabs = VINITabs() + self.tabs.setWidth("100%") + self.tabs.setHeight("100%") + self.initWidget(self.tabs) def init(): return SinkInfo("VINI", "Specify VINI Resources", VINI)