Added Node selection and Sliver (attribute) configuration panels to
authorAndy Bavier <acb@localhost.localdomain>
Thu, 3 Jun 2010 14:00:12 +0000 (10:00 -0400)
committerAndy Bavier <acb@localhost.localdomain>
Thu, 3 Jun 2010 14:00:12 +0000 (10:00 -0400)
PlanetLab and VINI.

LinkPanel.py [new file with mode: 0644]
NodePanel.py [new file with mode: 0644]
PlanetLab.py
SfaData.py
SliverPanel.py [new file with mode: 0644]
VINI.py

diff --git a/LinkPanel.py b/LinkPanel.py
new file mode 100644 (file)
index 0000000..cc36bc3
--- /dev/null
@@ -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 (file)
index 0000000..b7333ba
--- /dev/null
@@ -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()
index 50407c7..6488da9 100644 (file)
@@ -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)
index a26aaf9..e1abfac 100644 (file)
@@ -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 (file)
index 0000000..2ca4bbf
--- /dev/null
@@ -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 (file)
--- 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)