display ssh command in sliver detail view
[plstackapi.git] / planetstack / core / xoslib / objects / sliceplus.py
index 9187bff..6bbbfa2 100644 (file)
@@ -1,6 +1,7 @@
 from core.models import Slice, SlicePrivilege, SliceRole, Sliver, Site, Node, User
 from plus import PlusObjectMixin
 from operator import itemgetter, attrgetter
 from core.models import Slice, SlicePrivilege, SliceRole, Sliver, Site, Node, User
 from plus import PlusObjectMixin
 from operator import itemgetter, attrgetter
+from rest_framework.exceptions import APIException
 
 class SlicePlus(Slice, PlusObjectMixin):
     class Meta:
 
 class SlicePlus(Slice, PlusObjectMixin):
     class Meta:
@@ -13,10 +14,13 @@ class SlicePlus(Slice, PlusObjectMixin):
         self.getSliceInfo()
         self._site_allocation = self._sliceInfo["sitesUsed"]
         self._initial_site_allocation = self._site_allocation
         self.getSliceInfo()
         self._site_allocation = self._sliceInfo["sitesUsed"]
         self._initial_site_allocation = self._site_allocation
+        self._network_ports = self._sliceInfo["networkPorts"]
+        self._initial_network_ports = self._network_ports
 
     def getSliceInfo(self, user=None):
         if not self._sliceInfo:
             used_sites = {}
 
     def getSliceInfo(self, user=None):
         if not self._sliceInfo:
             used_sites = {}
+            ready_sites = {}
             used_deployments = {}
             sliverCount = 0
             sshCommands = []
             used_deployments = {}
             sliverCount = 0
             sshCommands = []
@@ -27,9 +31,11 @@ class SlicePlus(Slice, PlusObjectMixin):
                 used_deployments[deployment.name] = used_deployments.get(deployment.name, 0) + 1
                 sliverCount = sliverCount + 1
 
                 used_deployments[deployment.name] = used_deployments.get(deployment.name, 0) + 1
                 sliverCount = sliverCount + 1
 
-                if (sliver.instance_id and sliver.instance_name):
-                    sshCommand = 'ssh -o "ProxyCommand ssh -q %s@%s" ubuntu@%s' % (sliver.instance_id, sliver.node.name, sliver.instance_name)
-                    sshCommands.append(sshCommand);
+                sshCommand = sliver.get_ssh_command()
+                if sshCommand:
+                    sshCommands.append(sshCommand)
+
+                    ready_sites[site.name] = ready_sites.get(site.name, 0) + 1
 
             users = {}
             for priv in SlicePrivilege.objects.filter(slice=self):
 
             users = {}
             for priv in SlicePrivilege.objects.filter(slice=self):
@@ -37,13 +43,26 @@ class SlicePlus(Slice, PlusObjectMixin):
                     users[priv.user.id] = {"name": priv.user.email, "id": priv.user.id, "roles": []}
                 users[priv.user.id]["roles"].append(priv.role.role)
 
                     users[priv.user.id] = {"name": priv.user.email, "id": priv.user.id, "roles": []}
                 users[priv.user.id]["roles"].append(priv.role.role)
 
+            # XXX this assumes there is only one network that can have ports bound
+            # to it for a given slice. This is intended for the tenant view, which
+            # will obey this field.
+            networkPorts = ""
+            for networkSlice in self.networkslices.all():
+                network = networkSlice.network
+                if (network.owner.id != self.id):
+                    continue
+                if network.ports:
+                    networkPorts = network.ports
+
             self._sliceInfo= {"sitesUsed": used_sites,
             self._sliceInfo= {"sitesUsed": used_sites,
+                    "sitesReady": ready_sites,
                     "deploymentsUsed": used_deployments,
                     "sliverCount": sliverCount,
                     "siteCount": len(used_sites.keys()),
                     "users": users,
                     "roles": [],
                     "deploymentsUsed": used_deployments,
                     "sliverCount": sliverCount,
                     "siteCount": len(used_sites.keys()),
                     "users": users,
                     "roles": [],
-                    "sshCommands": sshCommands}
+                    "sshCommands": sshCommands,
+                    "networkPorts": networkPorts}
 
         if user:
             auser = self._sliceInfo["users"].get(user.id, None)
 
         if user:
             auser = self._sliceInfo["users"].get(user.id, None)
@@ -52,6 +71,14 @@ class SlicePlus(Slice, PlusObjectMixin):
 
         return self._sliceInfo
 
 
         return self._sliceInfo
 
+    @property
+    def site_ready(self):
+        return self.getSliceInfo()["sitesReady"]
+
+    @site_ready.setter
+    def site_ready(self, value):
+        pass
+
     @property
     def site_allocation(self):
         return self._site_allocation
     @property
     def site_allocation(self):
         return self._site_allocation
@@ -79,20 +106,12 @@ class SlicePlus(Slice, PlusObjectMixin):
 
     @property
     def network_ports(self):
 
     @property
     def network_ports(self):
-        # XXX this assumes there is only one network that can have ports bound
-        # to it for a given slice. This is intended for the tenant view, which
-        # will obey this field.
-        networkPorts = ""
-        for networkSlice in self.networkslices.all():
-            network = networkSlice.network
-            if network.ports:
-                networkPorts = network.ports
-
-        return networkPorts
+        return self._network_ports
 
     @network_ports.setter
     def network_ports(self, value):
 
     @network_ports.setter
     def network_ports(self, value):
-        print "XXX set networkPorts to", value
+        self._network_ports = value
+        #print "XXX set networkPorts to", value
 
     @staticmethod
     def select_by_user(user):
 
     @staticmethod
     def select_by_user(user):
@@ -121,6 +140,8 @@ class SlicePlus(Slice, PlusObjectMixin):
 
         super(SlicePlus, self).save(*args, **kwargs)
 
 
         super(SlicePlus, self).save(*args, **kwargs)
 
+        # try things out first
+
         updated_sites = (self._site_allocation != self._initial_site_allocation) or updated_image or updated_flavor
         if updated_sites:
             self.save_site_allocation(noAct=True, reset=(updated_image or updated_flavor))
         updated_sites = (self._site_allocation != self._initial_site_allocation) or updated_image or updated_flavor
         if updated_sites:
             self.save_site_allocation(noAct=True, reset=(updated_image or updated_flavor))
@@ -128,12 +149,20 @@ class SlicePlus(Slice, PlusObjectMixin):
         if self._update_users:
             self.save_users(noAct=True)
 
         if self._update_users:
             self.save_users(noAct=True)
 
+        if (self._network_ports != self._initial_network_ports):
+            self.save_network_ports(noAct=True)
+
+        # now actually save them
+
         if updated_sites:
             self.save_site_allocation(reset=(updated_image or updated_flavor))
 
         if self._update_users:
             self.save_users()
 
         if updated_sites:
             self.save_site_allocation(reset=(updated_image or updated_flavor))
 
         if self._update_users:
             self.save_users()
 
+        if (self._network_ports != self._initial_network_ports):
+            self.save_network_ports()
+
     def save_site_allocation(self, noAct = False, reset=False):
         print "save_site_allocation, reset=",reset
 
     def save_site_allocation(self, noAct = False, reset=False):
         print "save_site_allocation, reset=",reset
 
@@ -167,7 +196,7 @@ class SlicePlus(Slice, PlusObjectMixin):
                 nodes = self.get_node_allocation([site])
 
                 if (not nodes):
                 nodes = self.get_node_allocation([site])
 
                 if (not nodes):
-                    raise ValueError("no nodes in site %s" % site_name)
+                    raise APIException(detail="no nodes in site %s" % site_name)
 
                 while (len(slivers) < desired_allocation):
                     # pick the least allocated node
 
                 while (len(slivers) < desired_allocation):
                     # pick the least allocated node
@@ -217,6 +246,36 @@ class SlicePlus(Slice, PlusObjectMixin):
 
                  print "deleted user id", user_id
 
 
                  print "deleted user id", user_id
 
+    def save_network_ports(self, noAct=False):
+        # First search for any network that already has a filled in 'ports'
+        # field. We'll assume there can only be one, so it must be the right
+        # one.
+        for networkSlice in self.networkslices.all():
+            network = networkSlice.network
+            if (network.owner.id != self.id):
+                continue
+            if network.ports:
+                network.ports = self._network_ports
+                if (not noAct):
+                    network.save()
+                return
+
+        # Now try a network that is a "NAT", since setting ports on a non-NAT
+        # network doesn't make much sense.
+        for networkSlice in self.networkslices.all():
+            network = networkSlice.network
+            if (network.owner.id != self.id):
+                continue
+            if network.template.translation=="NAT":
+                network.ports = self._network_ports
+                if (not noAct):
+                    network.save()
+                return
+
+        # uh oh, we didn't find a network
+
+        raise APIException(detail="No network was found that ports could be set on")
+