Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/core/models/sliver.py b/planetstack/core/models/sliver.py
index 44a6af1..9c00cee 100644
--- a/planetstack/core/models/sliver.py
+++ b/planetstack/core/models/sliver.py
@@ -26,7 +26,16 @@
numberCores = models.IntegerField(verbose_name="Number of Cores", help_text="Number of cores for sliver", default=0)
tags = generic.GenericRelation(Tag)
- def __unicode__(self): return u'%s' % (self.instance_name)
+ def __unicode__(self):
+ if self.instance_name:
+ return u'%s' % (self.instance_name)
+ elif self.id:
+ return u'uninstantiated-%s' % str(self.id)
+ elif self.slice:
+ return u'unsaved-sliver on %s' % self.slice.name
+ else:
+ return u'unsaved-sliver'
+
def save(self, *args, **kwds):
if not self.name:
diff --git a/planetstack/openstack/observer.py b/planetstack/openstack/observer.py
index 73bb114..d8c3c61 100644
--- a/planetstack/openstack/observer.py
+++ b/planetstack/openstack/observer.py
@@ -37,6 +37,7 @@
return
while True:
try:
+ start_time=time.time()
logger.info('Observer run loop')
#self.sync_roles()
@@ -46,6 +47,8 @@
except:
logger.log_exc("Exception in sync_tenants")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync tenants took %f seconds'%(finish_time-start_time))
logger.info('Calling sync users')
try:
@@ -53,6 +56,8 @@
except:
logger.log_exc("Exception in sync_users")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync users took %f seconds'%(finish_time-start_time))
logger.info('Calling sync tenant roles')
try:
@@ -67,6 +72,8 @@
except:
logger.log_exc("Exception in sync slivers")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync slivers took %f seconds'%(finish_time-start_time))
logger.info('Calling sync sliver ips')
try:
@@ -74,6 +81,8 @@
except:
logger.log_exc("Exception in sync_sliver_ips")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync sliver ips took %f seconds'%(finish_time-start_time))
logger.info('Calling sync networks')
try:
@@ -81,6 +90,8 @@
except:
logger.log_exc("Exception in sync_networks")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync networks took %f seconds'%(finish_time-start_time))
logger.info('Calling sync network slivers')
try:
@@ -88,6 +99,8 @@
except:
logger.log_exc("Exception in sync_network_slivers")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync network sliver ips took %f seconds'%(finish_time-start_time))
logger.info('Calling sync external routes')
try:
@@ -95,6 +108,8 @@
except:
logger.log_exc("Exception in sync_external_routes")
traceback.print_exc()
+ finish_time = time.time()
+ logger.info('Sync external routes took %f seconds'%(finish_time-start_time))
logger.info('Waiting for event')
tBeforeWait = time.time()
@@ -329,11 +344,16 @@
for instance in instances:
if instance.uuid not in sliver_dict:
try:
- # lookup tenant and update context
- tenant = self.manager.driver.shell.keystone.tenants.find(id=instance.project_id)
- self.manager.init_admin(tenant=tenant.name)
+ # lookup tenant and update context
+ try:
+ tenant = self.manager.driver.shell.keystone.tenants.find(id=instance.project_id)
+ tenant_name = tenant.name
+ except:
+ tenant_name = None
+ logger.info("exception while retrieving tenant %s. Deleting instance using root tenant." % instance.project_id)
+ self.manager.init_admin(tenant=tenant_name)
self.manager.driver.destroy_instance(instance.uuid)
- logger.info("destroyed sliver: %s" % (instance))
+ logger.info("destroyed sliver: %s" % (instance.uuid))
except:
logger.log_exc("destroy sliver failed: %s" % instance)
diff --git a/planetstack/tests/networktest.py b/planetstack/tests/networktest.py
new file mode 100644
index 0000000..7f3cf70
--- /dev/null
+++ b/planetstack/tests/networktest.py
@@ -0,0 +1,195 @@
+"""
+ Network Data Model Test
+
+ 1) Create a slice1
+ 2) Create sliver1 on slice1
+ 3) Verify one quantum network created for sliver1
+ 4) Create a private network, network1
+ 5) Connect network1 to slice1
+ 6) Create sliver1_2 on slice1
+ 7) Verify two quantum networks created for sliver1_2
+"""
+
+import os
+import json
+import sys
+import time
+
+sys.path.append("/opt/planetstack")
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
+from openstack.manager import OpenStackManager
+from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
+
+from planetstacktest import PlanetStackTest, fail_unless, fail
+
+class NetworkTest(PlanetStackTest):
+ def __init__(self):
+ PlanetStackTest.__init__(self)
+
+ def wait_for_ports(self, sliver, count=1, max_time=120):
+ print "waiting for %d ports on %s" % (count, str(sliver))
+ while max_time>0:
+ ports = self.manager.driver.shell.quantum.list_ports(device_id=sliver.instance_id)["ports"]
+ if len(ports)==count:
+ return ports
+
+ fail_unless(len(ports)<=count, "too many ports")
+
+ time.sleep(10)
+ max_time = max_time - 10
+
+ fail("timed out while waiting for port creation")
+
+ def ports_to_networks(self, ports):
+ networks = []
+ for port in ports:
+ port_networks = networks + self.manager.driver.shell.quantum.list_networks(id=port["network_id"])["networks"]
+ for network in port_networks:
+ if not (network in networks):
+ networks.append(network)
+ return networks
+
+ def ports_to_network_names(self, ports):
+ network_names = []
+ for network in self.ports_to_networks(ports):
+ network_names.append(network["name"])
+ return network_names
+
+ def verify_network_names(self, ports, network_names):
+ port_network_names = sorted(self.ports_to_network_names(ports))
+ network_names = sorted(network_names)
+ fail_unless(port_network_names == network_names, "mismatched network names: %s != %s" % (str(port_network_names), str(network_names)))
+ print " verified network ports to", ",".join(port_network_names)
+
+ def test_slice1(self):
+ slice1Name = self.make_slice_name()
+ slice1 = Slice(name = slice1Name,
+ omf_friendly=True,
+ site=self.testSite,
+ creator=self.testUser)
+ slice1=self.save_and_wait_for_enacted(slice1, nonempty_fields=["tenant_id"])
+
+ sliver1 = Sliver(image = self.testImage,
+ creator=self.testUser,
+ slice=slice1,
+ node=self.testNode,
+ deploymentNetwork=self.testDeployment)
+ sliver1=self.save_and_wait_for_enacted(sliver1, nonempty_fields=["instance_id", "ip"])
+
+ # sliver1 should have only one port, its private network
+ ports = self.wait_for_ports(sliver1, count=1)
+ self.verify_network_names(ports, [slice1.name])
+
+ network1 = Network(name = slice1Name + "-pvt",
+ template = self.get_network_template("private"),
+ owner = slice1)
+ network1=self.save_and_wait_for_enacted(network1, nonempty_fields=["network_id", "subnet_id", "router_id", "subnet"])
+
+ network1_slice1 = NetworkSlice(network=network1, slice=slice1)
+ network1_slice1.save() # does not need to be enacted
+
+ sliver1_2 = Sliver(image = self.testImage,
+ creator=self.testUser,
+ slice=slice1,
+ node=self.testNode,
+ deploymentNetwork=self.testDeployment)
+ sliver1_2=self.save_and_wait_for_enacted(sliver1_2, nonempty_fields=["instance_id", "ip"])
+
+ ports = self.wait_for_ports(sliver1_2, count=2)
+ self.verify_network_names(ports, [slice1.name, network1.name])
+
+ self.slice1 = slice1
+ self.network1 = network1
+
+ def test_slice2(self):
+ slice2Name = self.make_slice_name()
+ slice2 = Slice(name = slice2Name,
+ omf_friendly=True,
+ site=self.testSite,
+ creator=self.testUser)
+ slice2=self.save_and_wait_for_enacted(slice2, nonempty_fields=["tenant_id"])
+
+ network2 = Network(name = slice2Name + "-pvt",
+ template = self.get_network_template("private"),
+ owner = slice2)
+ network2=self.save_and_wait_for_enacted(network2, nonempty_fields=["network_id", "subnet_id", "router_id", "subnet"])
+
+ network2_slice2 = NetworkSlice(network=network2, slice=slice2)
+ network2_slice2.save() # does not need to be enacted
+
+ sliver2_1 = Sliver(image = self.testImage,
+ creator=self.testUser,
+ slice=slice2,
+ node=self.testNode,
+ deploymentNetwork=self.testDeployment)
+ sliver2_1=self.save_and_wait_for_enacted(sliver2_1, nonempty_fields=["instance_id", "ip"])
+
+ ports = self.wait_for_ports(sliver2_1, count=2)
+ self.verify_network_names(ports, [slice2.name, network2.name])
+
+ self.slice2 = slice2
+ self.network2 = network2
+
+ def test_shared_private_net(self):
+ # connect network2 to slice1
+ self.network2.permittedSlices.add(self.slice1)
+ network2_slice1 = NetworkSlice(network=self.network2, slice=self.slice1)
+ network2_slice1.save()
+
+ sliver1_3 = Sliver(image = self.testImage,
+ creator=self.testUser,
+ slice=self.slice1,
+ node=self.testNode,
+ deploymentNetwork=self.testDeployment)
+ sliver1_3=self.save_and_wait_for_enacted(sliver1_3, nonempty_fields=["instance_id", "ip"])
+
+ ports = self.wait_for_ports(sliver1_3, count=3)
+ self.verify_network_names(ports, [self.slice1.name, self.network1.name, self.network2.name])
+
+ def test_nat_net(self):
+ slice3Name = self.make_slice_name()
+ slice3 = Slice(name = slice3Name,
+ omf_friendly=True,
+ site=self.testSite,
+ creator=self.testUser)
+ slice3=self.save_and_wait_for_enacted(slice3, nonempty_fields=["tenant_id"])
+
+ network3 = Network(name = slice3Name + "-nat",
+ template = self.get_network_template("private-nat"),
+ owner = slice3)
+ # note that router_id will not be filled in for nat-net, since nat-net has no routers
+ network3=self.save_and_wait_for_enacted(network3, nonempty_fields=["network_id", "subnet_id", "subnet"])
+
+ network3_slice3 = NetworkSlice(network=network3, slice=slice3)
+ network3_slice3.save() # does not need to be enacted
+
+ sliver3_1 = Sliver(image = self.testImage,
+ creator=self.testUser,
+ slice=slice3,
+ node=self.testNode,
+ deploymentNetwork=self.testDeployment)
+ sliver3_1=self.save_and_wait_for_enacted(sliver3_1, nonempty_fields=["instance_id", "ip"])
+
+ ports = self.wait_for_ports(sliver3_1, count=2)
+ self.verify_network_names(ports, [slice3.name, "nat-net"])
+
+ def run(self):
+ self.setup()
+ try:
+ self.test_slice1()
+ self.test_slice2()
+ self.test_shared_private_net()
+ self.test_nat_net()
+ print "SUCCESS"
+ finally:
+ self.cleanup()
+
+def main():
+ NetworkTest().run()
+
+if __name__=="__main__":
+ main()
+
+
+
diff --git a/planetstack/tests/planetstacktest.py b/planetstack/tests/planetstacktest.py
new file mode 100644
index 0000000..77ed95f
--- /dev/null
+++ b/planetstack/tests/planetstacktest.py
@@ -0,0 +1,94 @@
+import os
+import json
+import sys
+import time
+
+sys.path.append("/opt/planetstack")
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
+from openstack.manager import OpenStackManager
+from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
+
+TEST_SITE_NAME = "Princeton University"
+TEST_USER_EMAIL = "sbaker@planetstack.org"
+TEST_IMAGE_NAME = "Fedora 16 LXC rev 1.3"
+TEST_NODE_NAME = "viccidev3.cs.princeton.edu"
+TEST_DEPLOYMENT_NAME = "VICCI"
+
+def fail(msg):
+ print msg
+ sys.exit(-1)
+
+def fail_unless(condition, msg):
+ if not condition:
+ fail(msg)
+
+class PlanetStackTest:
+ def __init__(self):
+ self.objs_saved = []
+ self.counter = 0
+
+ def setup(self):
+ self.manager = OpenStackManager()
+
+ print "getting test site"
+ self.testSite = Site.objects.get(name=TEST_SITE_NAME)
+
+ print "getting test user"
+ self.testUser = User.objects.get(email=TEST_USER_EMAIL)
+
+ print "getting test image"
+ self.testImage = Image.objects.get(name=TEST_IMAGE_NAME)
+
+ print "getting test node"
+ self.testNode = Node.objects.get(name=TEST_NODE_NAME)
+
+ print "getting test deployment"
+ self.testDeployment = Deployment.objects.get(name=TEST_DEPLOYMENT_NAME)
+
+ def save_and_wait_for_enacted(self, x, nonempty_fields=[]):
+ print "saving", x.__class__.__name__, str(x)
+ x.save()
+ self.objs_saved.append(x)
+ print " waiting for", str(x), "to be enacted"
+ tStart = time.time()
+ while True:
+ new_x = x.__class__.objects.get(id=x.id)
+ if (new_x.enacted != None) and (new_x.enacted >= new_x.updated):
+ print " ", str(x), "has been enacted"
+ break
+ time.sleep(5)
+
+ if nonempty_fields:
+ print " waiting for", ", ".join(nonempty_fields), "to be nonempty"
+ while True:
+ new_x = x.__class__.objects.get(id=x.id)
+ keep_waiting=False
+ for field in nonempty_fields:
+ if not getattr(new_x, field, None):
+ keep_waiting=True
+ if not keep_waiting:
+ break
+
+ print " saved and enacted in %d seconds" % int(time.time() - tStart)
+
+ return new_x
+
+ def make_slice_name(self):
+ self.counter = self.counter +1
+ return "test-" + str(time.time()) + "." + str(self.counter)
+
+ def get_network_template(self,name):
+ template = NetworkTemplate.objects.get(name=name)
+ return template
+
+ def cleanup(self):
+ print "cleaning up"
+ print "press return"
+ sys.stdin.readline()
+ for obj in self.objs_saved:
+ try:
+ print " deleting", str(obj)
+ obj.delete()
+ except:
+ print "failed to delete", str(obj)
diff --git a/planetstack/tests/slivertest.py b/planetstack/tests/slivertest.py
new file mode 100644
index 0000000..271fe5b
--- /dev/null
+++ b/planetstack/tests/slivertest.py
@@ -0,0 +1,51 @@
+"""
+ Basic Sliver Test
+
+ 1) Create a slice1
+ 2) Create sliver1 on slice1
+"""
+
+import os
+import json
+import sys
+import time
+
+sys.path.append("/opt/planetstack")
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
+from openstack.manager import OpenStackManager
+from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
+
+from planetstacktest import PlanetStackTest, fail_unless
+
+class SliverTest(PlanetStackTest):
+ def __init__(self):
+ PlanetStackTest.__init__(self)
+
+ def run_sliver1(self):
+ slice1Name = self.make_slice_name()
+ slice1 = Slice(name = slice1Name,
+ omf_friendly=True,
+ site=self.testSite,
+ creator=self.testUser)
+ slice1=self.save_and_wait_for_enacted(slice1, nonempty_fields=["tenant_id"])
+
+ sliver1 = Sliver(image = self.testImage,
+ creator=self.testUser,
+ slice=slice1,
+ node=self.testNode,
+ deploymentNetwork=self.testDeployment)
+ sliver1=self.save_and_wait_for_enacted(sliver1, nonempty_fields=["instance_id", "ip"])
+
+ def run(self):
+ self.setup()
+ try:
+ self.run_sliver1()
+ finally:
+ self.cleanup()
+
+def main():
+ SliverTest().run()
+
+if __name__=="__main__":
+ main()