Finished first cut at VINI's LinkPanel
Andy Bavier [Thu, 3 Jun 2010 21:10:44 +0000 (17:10 -0400)]
LinkPanel.py
NodePanel.py
SfaData.py
SliverPanel.py
public/images/cancel.png [new file with mode: 0644]

index cc36bc3..ea7164f 100644 (file)
@@ -1,60 +1,82 @@
 from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas.ui.Grid import Grid
+from pyjamas.ui.DockPanel import DockPanel
 from pyjamas.ui.HorizontalPanel import HorizontalPanel
 from pyjamas.ui.CaptionPanel import CaptionPanel
-from pyjamas.ui.ListBox import ListBox
+from pyjamas.ui.CheckBox import CheckBox
 from pyjamas.ui.TextBox import TextBox
 from pyjamas.ui.Button import Button
 from pyjamas.ui.HTML import HTML
+from pyjamas.ui.Image import Image
 from pyjamas.ui import HasAlignment
 
-class AddPanel(CaptionPanel):
-    def __init__(self, top):
-        CaptionPanel.__init__(self, "Add virtual link")
+class TopPanel(DockPanel):
+    def __init__(self, top, bw, active = False):
+        DockPanel.__init__(self)
         self.top = top
-
+        self.setWidth("100%")
+        self.cb = CheckBox("Use virtual topology")
+        self.cb.setChecked(active)
+        self.cb.addClickListener(self)
         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()
+        self.tb = TextBox()
+        self.tb.setVisibleLength(8)
+        self.tb.setTextAlignment(self.tb.ALIGN_RIGHT)
+        self.tb.setText(bw)
+        hp.add(HTML("Default bandwidth: "))
+        hp.add(self.tb)
+        hp.add(HTML(" kbps"))
+
+        self.add(self.cb, DockPanel.WEST)
+        self.add(hp, DockPanel.EAST)
+        self.setCellHorizontalAlignment(hp, HasAlignment.ALIGN_RIGHT)
+
+    def onClick(self, sender):
+        if sender == self.cb:
+            if sender.isChecked():
+                self.top.build_topology()
+                self.top.refresh()
+            else:
+                self.top.clear_vlinks()
+                ## Unset vini_topo attribute?
+                self.top.refresh()
+
+    def getDefaultBW(self):
+        bw = self.tb.getText()
+        return bw
         
-
-class VlinkPanel(HorizontalPanel):
-    def __init__(self, top, description, bw):
-        HorizontalPanel.__init__(self)
+class VlinkPanel(DockPanel):
+    def __init__(self, top, handle, description, bw):
+        DockPanel.__init__(self)
+        self.handle = handle
         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):
+        hp1 = HorizontalPanel()
+        delete = Image("./images/cancel.png")
+        delete.addClickListener(self)
+        hp1.add(delete)
+        hp1.add(HTML(" %s" % self.description))
+        
+        hp2 = HorizontalPanel()
+        tb = TextBox()
+        tb.setVisibleLength(8)
+        tb.setTextAlignment(tb.ALIGN_RIGHT)
+        tb.setText(bw)
+        hp2.add(tb)
+        hp2.add(HTML(" kbps"))
+
+        self.add(hp1, DockPanel.WEST)
+        self.setCellHorizontalAlignment(hp1, HasAlignment.ALIGN_LEFT)
+        self.setCellWidth(hp1, "100%")
+
+        self.add(hp2, DockPanel.EAST)
+        self.setCellHorizontalAlignment(hp2, HasAlignment.ALIGN_RIGHT)
+        self.setWidth("100%")
+
+    def onClick(self, sender):
+        self.top.rspec.remove_vlink(self.handle)
         self.top.refresh()
 
 
@@ -63,18 +85,37 @@ class LinkPanel(VerticalPanel):
         VerticalPanel.__init__(self)
         self.data = sfadata
         self.rspec = rspec
-
+        self.defaultbw = 1000
         self.refresh()
 
     def refresh(self):
         self.clear()
-        self.add(AddPanel(self))
+        vlinks = self.rspec.get_vlink_list()
+
+        self.toppanel = TopPanel(self, self.defaultbw, (len(vlinks) > 0))
+        self.add(self.toppanel)
 
         cp = CaptionPanel("Virtual links")
         vp = VerticalPanel()
-        vlinks = self.rspec.get_vlink_list()
-        for (desc, bw) in vlinks:
-            vp.add(VlinkPanel(self, desc, bw))
+        vp.setWidth("100%")
+        for (handle, desc, bw) in vlinks:
+            vp.add(VlinkPanel(self, handle, desc, bw))
         cp.add(vp)
         self.add(cp)
+
+    def clear_vlinks(self):
+        vlinks = self.rspec.get_vlink_list()
+        for (handle, desc, bw) in vlinks:
+            self.rspec.remove_vlink(handle)
+
+    def build_topology(self):
+        nodes = self.rspec.get_sliver_list()
+        links = self.rspec.get_link_list()
+        self.defaultbw = self.toppanel.getDefaultBW()
+
+        for (name, end1nodes, end2nodes) in links:
+            for node1 in end1nodes:
+                for node2 in end2nodes:
+                    if (node1 in nodes) and (node2 in nodes):
+                        self.rspec.add_vlink(node1, node2, self.defaultbw)
                 
index b7333ba..a4c11e1 100644 (file)
@@ -108,8 +108,7 @@ class NodePanel(DockPanel):
         self.refresh()
 
     def apply(self, sender):
-        # Call sfi.py create via ViniData object
-        pass
+        self.data.applyRSpec(self.rspec)
 
     def reset(self, sender):
         self.rspec = self.data.getRSpec()
index e1abfac..343ad0e 100644 (file)
@@ -44,6 +44,16 @@ class SfaData:
         f.close()
         return xml
 
+    def applyRSpec(self, xml):
+        slice = self.getSlice()
+        filename = os.path.expanduser("~/.sfi/" + slice + ".rspec")
+        f = open(filename, "w")
+        f.write(xml)
+        f.close()
+        call(["sfi.py", "-u", self.getUser(), "-a", self.getAuthority(), 
+              "-r", self.registry, "-s", self.slicemgr, "create", 
+              slice, filename])
+
 class ViniData(SfaData):
     def __init__(self):
         SfaData.__init__(self)
@@ -54,6 +64,10 @@ class ViniData(SfaData):
         xml = SfaData.getRSpec(self)
         return RSpec(xml)
 
+    def applyRSpec(self, rspec):
+        xml = rspec.toxml()
+        SfaData.applyRSpec(self, xml)
+
 class PlanetLabData(SfaData):
     def __init__(self):
         SfaData.__init__(self)
@@ -64,6 +78,10 @@ class PlanetLabData(SfaData):
         xml = SfaData.getRSpec(self)
         return RSpec(xml)
 
+    def applyRSpec(self, rspec):
+        xml = rspec.toxml()
+        SfaData.applyRSpec(self, xml)
+
 class OpenCirrusData(SfaData):
     def __init__(self):
         SfaData.__init__(self)
index 2ca4bbf..bf91adb 100644 (file)
@@ -5,6 +5,7 @@ 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.Image import Image
 from pyjamas.ui import HasAlignment
 
 class AddPanel(CaptionPanel):
@@ -61,21 +62,20 @@ class AttributePanel(HorizontalPanel):
 
         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)
+        delete = Image("./images/cancel.png")
+        delete.addClickListener(self)
+        self.add(delete)
         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)
+    def onClick(self, sender):
+        if self.node:
+            self.top.rspec.remove_sliver_attribute(self.node, self.name, 
+                                                   self.value)
+        else:
+            self.top.rspec.remove_default_sliver_attribute(self.name, 
+                                                           self.value)
         self.top.refresh()
-
+        
 
 class SliverPanel(VerticalPanel):
     def __init__(self, sfadata, rspec):
diff --git a/public/images/cancel.png b/public/images/cancel.png
new file mode 100644 (file)
index 0000000..c149c2b
Binary files /dev/null and b/public/images/cancel.png differ