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 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 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):
     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()
 
         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)
 
 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"
     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)
 
     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"
     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"
 
 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 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 SfaData import ViniData
+from NodePanel import NodePanel
+from LinkPanel import LinkPanel
+from SliverPanel import SliverPanel
 
 
-class VINI(Sink):
+class VINITabs(TabPanel):
     def __init__(self):
     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()
 
         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)
 
 def init():
     return SinkInfo("VINI", "Specify VINI Resources", VINI)