Adding doc strings and tests
authorLucia Guevgeozian Odizzio <lucia.guevgeozian_odizzio@inria.fr>
Wed, 28 May 2014 07:06:42 +0000 (09:06 +0200)
committerLucia Guevgeozian Odizzio <lucia.guevgeozian_odizzio@inria.fr>
Wed, 28 May 2014 07:06:42 +0000 (09:06 +0200)
src/nepi/resources/omf/wilabt_node.py
src/nepi/resources/planetlab/sfa_node.py
src/nepi/util/sfaapi.py
test/lib/test_utils.py
test/resources/omf/wilab_node.py [new file with mode: 0755]
test/resources/planetlab/sfa_node.py

index c8807b4..80f076c 100644 (file)
@@ -83,6 +83,10 @@ class WilabtSfaNode(LinuxNode):
     
     @property
     def sfaapi(self):
+        """
+        Property to instanciate the SFA API based in sfi client.
+        For each SFA method called this instance is used.
+        """
         if not self._sfaapi:
             sfa_user = self.get("sfauser")
             sfa_sm = "http://www.wilab2.ilabt.iminds.be:12369/protogeni/xmlrpc/am/3.0"
@@ -104,7 +108,7 @@ class WilabtSfaNode(LinuxNode):
     def do_discover(self):
         """
         Based on the attributes defined by the user, discover the suitable 
-        nodes for provision.
+        node for provision.
         """
         if self._skip_provision():
             super(WilabtSfaNode, self).do_discover()
@@ -132,8 +136,8 @@ class WilabtSfaNode(LinuxNode):
 
     def do_provision(self):
         """
-        Add node to user's slice after verifing that the node is functioning
-        correctly.
+        Add node to user's slice and verifing that the node is functioning
+        correctly. Check ssh, omf rc running, hostname, file system.
         """
         if self._skip_provision():
             super(WilabtSfaNode, self).do_provision()
@@ -152,11 +156,17 @@ class WilabtSfaNode(LinuxNode):
                 time.sleep(300) # Timout for the testbed to allow a new reservation
             self._add_node_to_slice(node)
             t = 0
-            while not self._check_if_in_slice([node]) and t < timeout:
+            while not self._check_if_in_slice([node]) and t < timeout \
+                and not self._ecobj().abort:
                 t = t + 5
                 time.sleep(t)
                 self.debug("Waiting 5 seg for resources to be added")
                 continue
+
+            if not self._check_if_in_slice([node]):
+                self.debug("Couldn't add node %s to slice" % node)
+                self.fail_node_not_available(node)
+
             self._get_username()
             ssh_ok = self._check_ssh_loop()          
 
@@ -191,16 +201,28 @@ class WilabtSfaNode(LinuxNode):
         super(WilabtSfaNode, self).do_provision()
 
     def _blacklisted(self, host_hrn):
+        """
+        Check in the SFA API that the node is not in the blacklist.
+        """
         if self.sfaapi.blacklisted(host_hrn):
            self.fail_node_not_available(host_hrn)
         return False
 
     def _reserved(self, host_hrn):
+        """
+        Check in the SFA API that the node is not in the reserved
+        list.
+        """
         if self.sfaapi.reserved(host_hrn):
             self.fail_node_not_available(host_hrn)
         return False
 
     def _get_username(self):
+        """
+        Get the username for login in to the nodes from RSpec.
+        Wilabt username is not made out of any convention, it
+        has to be retrived from the manifest RSpec.
+        """
         slicename = self.get("slicename")
         if self._username is None:
             slice_info = self.sfaapi.get_slice_resources(slicename)
@@ -210,6 +232,10 @@ class WilabtSfaNode(LinuxNode):
             self._username = username
             
     def _check_ssh_loop(self):
+        """
+        Check that the ssh login is possible. In wilabt is done
+        through the gateway because is private testbed.
+        """
         t = 0
         timeout = 10
         ssh_ok = False
@@ -228,6 +254,9 @@ class WilabtSfaNode(LinuxNode):
         return ssh_ok
 
     def _check_fs(self):
+        """
+        Check file system, /proc well mounted.
+        """
         cmd = 'mount |grep proc'
         ((out, err), proc) = self.execute(cmd)
         if out.find("/proc type proc") < 0:
@@ -237,6 +266,9 @@ class WilabtSfaNode(LinuxNode):
         return True
 
     def _check_omfrc(self):
+        """
+        Check that OMF 6 resource controller is running.
+        """
         cmd = 'ps aux|grep omf'
         ((out, err), proc) = self.execute(cmd)
         if out.find("/usr/local/rvm/gems/ruby-1.9.3-p286@omf/bin/omf_rc") < 0:
@@ -244,6 +276,9 @@ class WilabtSfaNode(LinuxNode):
         return True
 
     def _check_hostname(self):
+        """
+        Check that the hostname in the image is not set to localhost.
+        """
         cmd = 'hostname'
         ((out, err), proc) = self.execute(cmd)
         if 'localhost' in out.lower():
@@ -251,16 +286,32 @@ class WilabtSfaNode(LinuxNode):
         return True 
 
     def _add_node_to_slice(self, host_hrn):
+        """
+        Add node to slice, using SFA API. Actually Wilabt testbed
+        doesn't allow adding nodes, in fact in the API there is method
+        to group all the nodes instanciated as WilabtSfaNodes and the
+        Allocate and Provision is done with the last call at 
+        sfaapi.add_resource_to_slice_batch.
+        """
         self.info(" Adding node to slice ")
         slicename = self.get("slicename")
         self.sfaapi.add_resource_to_slice_batch(slicename, host_hrn)
 
     def _delete_from_slice(self):
+        """
+        Delete every node from slice, using SFA API.
+        Wilabt doesn't allow to remove one sliver so this method 
+        remove every slice from the slice.
+        """
+
         self.warning(" Deleting all slivers from slice ")
         slicename = self.get("slicename")
         self.sfaapi.remove_all_from_slice(slicename)
 
     def _get_hostname(self):
+        """
+        Get the attribute hostname.
+        """
         hostname = self.get("hostname")
         if hostname:
             return hostname
@@ -270,7 +321,7 @@ class WilabtSfaNode(LinuxNode):
     def _set_hostname_attr(self, node):
         """
         Query SFAAPI for the hostname of a certain host hrn and sets the
-        attribute hostname, it will over write the previous value
+        attribute hostname, it will over write the previous value.
         """
         hosts_hrn = self.sfaapi.get_resources_hrn()
         for hostname, hrn  in hosts_hrn.iteritems():
@@ -281,7 +332,7 @@ class WilabtSfaNode(LinuxNode):
     def _check_if_in_slice(self, hosts_hrn):
         """
         Check using SFA API if any host hrn from hosts_hrn is in the user's
-        slice
+        slice.
         """
         slicename = self.get("slicename")
         slice_nodes = self.sfaapi.get_slice_resources(slicename)['resource']
@@ -294,7 +345,7 @@ class WilabtSfaNode(LinuxNode):
 
     def _do_ping(self, hostname):
         """
-        Perform ping command on node's IP matching hostname
+        Perform ping command on node's IP matching hostname.
         """
         ping_ok = False
         guser = self.get("gatewayUser")
@@ -310,7 +361,7 @@ class WilabtSfaNode(LinuxNode):
 
     def _blacklist_node(self, host_hrn):
         """
-        Add node mal functioning node to blacklist
+        Add mal functioning node to blacklist (in SFA API).
         """
         self.warning(" Blacklisting malfunctioning node ")
         self.sfaapi.blacklist_resource(host_hrn)
@@ -322,13 +373,13 @@ class WilabtSfaNode(LinuxNode):
     def _put_node_in_provision(self, host_hrn):
         """
         Add node to the list of nodes being provisioned, in order for other RMs
-        to not try to provision the same one again
+        to not try to provision the same one again.
         """
         self.sfaapi.reserve_resource(host_hrn)
 
     def _get_ip(self, hostname):
         """
-        Query PLCAPI for the IP of a node with certain node id
+        Query cache for the IP of a node with certain hostname
         """
         try:
             ip = sshfuncs.gethostbyname(hostname)
index 59f1df0..ca7ba36 100644 (file)
@@ -192,6 +192,10 @@ class PlanetlabSfaNode(LinuxNode):
     
     @property
     def sfaapi(self):
+        """
+        Property to instanciate the SFA API based in sfi client.
+        For each SFA method called this instance is used.
+        """
         if not self._sfaapi:
             sfa_user = self.get("sfauser")
             sfa_sm = "http://sfa3.planet-lab.eu:12346/"
@@ -278,19 +282,26 @@ class PlanetlabSfaNode(LinuxNode):
 #               self.fail_not_enough_nodes() 
 #    
     def _blacklisted(self, host_hrn):
+        """
+        Check in the SFA API that the node is not in the blacklist.
+        """
         if self.sfaapi.blacklisted(host_hrn):
            self.fail_node_not_available(host_hrn)
         return False
 
     def _reserved(self, host_hrn):
+        """
+        Check in the SFA API that the node is not in the reserved
+        list.
+        """
         if self.sfaapi.reserved(host_hrn):
             self.fail_node_not_available(host_hrn)
         return False
             
     def do_provision(self):
         """
-        Add node to user's slice after verifing that the node is functioning
-        correctly.
+        Add node to user's slice and verifing that the node is functioning
+        correctly. Check ssh, file system.
         """
         if self._skip_provision():
             super(PlanetlabSfaNode, self).do_provision()
@@ -525,18 +536,28 @@ class PlanetlabSfaNode(LinuxNode):
 #        return self.plapi.get_nodes(filters, fields=['node_id'])
 #
     def _add_node_to_slice(self, host_hrn):
+        """
+        Add node to slice, using SFA API.
+        """
         self.info(" Adding node to slice ")
         slicename = self.get("username").replace('_', '.')
         slicename = 'ple.' + slicename
         self.sfaapi.add_resource_to_slice(slicename, host_hrn)
 
     def _delete_from_slice(self):
+        """
+        Delete every node from slice, using SFA API.
+        Sfi client doesn't work for particular node urns.
+        """
         self.warning(" Deleting node from slice ")
         slicename = self.get("username").replace('_', '.')
         slicename = 'ple.' + slicename
         self.sfaapi.remove_all_from_slice(slicename)
 
     def _get_hostname(self):
+        """
+        Get the attribute hostname.
+        """
         hostname = self.get("hostname")
         if hostname:
             return hostname
@@ -546,7 +567,7 @@ class PlanetlabSfaNode(LinuxNode):
     def _set_hostname_attr(self, node):
         """
         Query SFAAPI for the hostname of a certain host hrn and sets the
-        attribute hostname, it will over write the previous value
+        attribute hostname, it will over write the previous value.
         """
         hosts_hrn = self.sfaapi.get_resources_hrn()
         for hostname, hrn  in hosts_hrn.iteritems():
@@ -556,7 +577,7 @@ class PlanetlabSfaNode(LinuxNode):
     def _check_if_in_slice(self, hosts_hrn):
         """
         Check using SFA API if any host hrn from hosts_hrn is in the user's
-        slice
+        slice.
         """
         slicename = self.get("username").replace('_', '.')
         slicename = 'ple.' + slicename
@@ -569,7 +590,7 @@ class PlanetlabSfaNode(LinuxNode):
 
     def _do_ping(self, hostname):
         """
-        Perform ping command on node's IP matching hostname
+        Perform ping command on node's IP matching hostname.
         """
         ping_ok = False
         ip = self._get_ip(hostname)
@@ -585,7 +606,7 @@ class PlanetlabSfaNode(LinuxNode):
 
     def _blacklist_node(self, host_hrn):
         """
-        Add node mal functioning node to blacklist
+        Add mal functioning node to blacklist (in SFA API).
         """
         self.warning(" Blacklisting malfunctioning node ")
         self.sfaapi.blacklist_resource(host_hrn)
index 48dfb48..13f45e4 100644 (file)
@@ -36,7 +36,7 @@ from nepi.util.sfarspec_proc import SfaRSpecProcessing
 
 class SFAAPI(object):
     """
-    API for quering the SFA service.
+    API for quering the SFA service. It uses Sfi class from the tool sfi client.
     """
     def __init__(self, sfi_user, sfi_auth, sfi_registry, sfi_sm, private_key, ec,
         batch, rtype, timeout):
@@ -73,6 +73,10 @@ class SFAAPI(object):
             self._set_blacklist()
 
     def _set_blacklist(self):
+        """
+        Initialize the blacklist with previous nodes blacklisted, in 
+        previous runs.
+        """
         nepi_home = os.path.join(os.path.expanduser("~"), ".nepi")
         plblacklist_file = os.path.join(nepi_home, "plblacklist.txt")
         with open(plblacklist_file, 'r') as f:
@@ -82,6 +86,12 @@ class SFAAPI(object):
                     self._blacklist.add(host)
 
     def _get_total_res(self):
+        """
+        Get the total amount of resources instanciated using this API,
+        to be able to add them using the same Allocate and Provision
+        call at once. Specially for Wilabt testbed that doesn't allow 
+        to add slivers after the slice already has some.
+        """
         rms = list()
         res_gids = self._ec.resources
         for gid in res_gids:
@@ -92,7 +102,8 @@ class SFAAPI(object):
 
     def _sfi_exec_method(self, command, slicename=None, rspec=None, urn=None):
         """
-        Execute sfi method.
+        Execute sfi method, which correspond to SFA call. It can be the following
+        calls: Describe, Delete, Allocate, Provision, ListResources.
         """
         if command in ['describe', 'delete', 'allocate', 'provision']:
             if not slicename:
@@ -232,10 +243,10 @@ class SFAAPI(object):
     def add_resource_to_slice_batch(self, slicename, resource_hrn, leases=None):
         """
         Method to add all resources together to the slice. Previous deletion of slivers.
+        Specially used for wilabt that doesn't allow to add more resources to the slice
+        after some resources are added. Every sliver have to be deleted and the batch 
+        has to be added at once.
         """
-        # Specially used for wilabt that doesn't allow to add more resources to the slice
-        # after some resources are added. Every sliver have to be deleted and the batch 
-        # has to be added at once.
         self._count += 1
         self._slice_resources_batch.append(resource_hrn)
         resources_hrn_new = list()
@@ -295,8 +306,8 @@ class SFAAPI(object):
 
     def remove_resource_from_slice(self, slicename, resource_hrn, leases=None):
         """
-        Get the list of resources' urn, build the rspec string and call the allocate 
-        and provision method.
+        Remove slivers from slice. Currently sfi doesn't support removing particular
+        slivers.
         """
         resource_urn = self._get_resources_urn([resource_hrn]).pop()
         with self.lock_slice:
@@ -309,6 +320,9 @@ class SFAAPI(object):
     def remove_all_from_slice(self, slicename):
         """
         De-allocate and de-provision all slivers of the named slice.
+        Currently sfi doesn't support removing particular
+        slivers, so this method works only for removing every sliver. Setting the
+        resource_hrn parameter is not necessary.
         """
         with self.lock_slice:
             try:
@@ -329,6 +343,10 @@ class SFAAPI(object):
         return resources_urn
 
     def blacklist_resource(self, resource_hrn):
+        """
+        Adding resource_hrn to blacklist, and taking 
+        the resource from the reserved list.
+        """
         with self.lock_blist:
             self._blacklist.add(resource_hrn)
         with self.lock_resv:
@@ -336,15 +354,24 @@ class SFAAPI(object):
                 self._reserved.remove(resource_hrn)
 
     def blacklisted(self, resource_hrn):
+        """
+        Check if the resource is in the blacklist. 
+        """
         with self.lock_blist:
             if resource_hrn in self._blacklist:
                 return True
         return False
 
     def reserve_resource(self, resource_hrn):
+        """
+        Add resource to the reserved list.
+        """
         self._reserved.add(resource_hrn)
 
     def reserved(self, resource_hrn):
+        """
+        Check that the resource in not reserved.
+        """
         with self.lock_resv:
             if resource_hrn in self._reserved:
                 return True
index 1940552..7fcb980 100644 (file)
@@ -122,3 +122,16 @@ def skipIfNotSfaCredentials(func):
 
     return wrapped
 
+def skipIfNotSfi(func):
+    name = func.__name__
+    def wrapped(*args, **kwargs):
+        try:
+            from sfa.client.sfi import Sfi
+            from sfa.util.xrn import hrn_to_urn
+        except ImportError:
+            print "*** WARNING: Skipping test %s: sfi-client or sfi-common not installed\n" % name
+            return
+
+        return func(*args, **kwargs)
+
+    return wrapped
diff --git a/test/resources/omf/wilab_node.py b/test/resources/omf/wilab_node.py
new file mode 100755 (executable)
index 0000000..5bca969
--- /dev/null
@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+#
+#    NEPI, a framework to manage network experiments
+#    Copyright (C) 2013 INRIA
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Lucia Guevgeozian <lucia.guevgeozian_odizzio@inria.fr>
+
+from nepi.execution.ec import ExperimentController
+from nepi.resources.omf.wilabt_node import WilabtSfaNode
+from nepi.util.sfaapi import SFAAPI, SFAAPIFactory
+
+from test_utils import skipIfNotSfi
+
+import os
+import time
+import unittest
+import multiprocessing
+
+class DummyEC(ExperimentController):
+    pass
+
+class WilabtSfaNodeFactoryTestCase(unittest.TestCase):
+
+    def test_creation_phase(self):
+        self.assertEquals(WilabtSfaNode._rtype, "WilabtSfaNode")
+        self.assertEquals(len(WilabtSfaNode._attributes), 17)
+
+class WilabtSfaNodeTestCase(unittest.TestCase):
+    """
+    This tests use inria_nepi slice, from the test instance of MyPLC
+    nepiplc.pl.sophia.inria.fr. This test can fail if the user running
+    the test does not have a user in this instance of MyPLC or is not
+    added to the inria_nepi slice.
+    """
+
+    def setUp(self):
+        self.ec = DummyEC()
+        slicepl = os.environ.get('SFA_SLICE')
+        slicename = ['ple'] + slicepl.split('_')
+        self.slicename = '.'.join(slicename)
+        self.sfauser = os.environ.get('SFA_USER')
+        self.sfaPrivateKey = os.environ.get('SFA_PK')
+        
+    @skipIfNotSfi
+    def test_a_sfaapi(self):
+        """
+        Check that the api to discover and reserve resources is well
+        instanciated, and is an instance of SFAAPI. Check that using
+        the same credentials, the same object of the api is used.
+        """
+        node1 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node1, "hostname", "zotacB5")
+        self.ec.set(node1, "slicename", self.slicename)
+        self.ec.set(node1, "sfauser", self.sfauser)
+        self.ec.set(node1, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node1, "gatewayUser", "nepi")
+        self.ec.set(node1, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node1, "cleanHome", True)
+        self.ec.set(node1, "cleanProcesses", True)
+
+        wnode_rm1 = self.ec.get_resource(node1)
+
+        self.assertIsNone(wnode_rm1._node_to_provision)
+
+        api1 = wnode_rm1.sfaapi
+        self.assertIsInstance(api1, SFAAPI)
+        self.assertEquals(len(api1._reserved), 0)
+        self.assertEquals(len(api1._blacklist), 0)
+
+        node2 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node2, "hostname", "zotacM20")
+        self.ec.set(node2, "slicename", self.slicename)
+        self.ec.set(node2, "sfauser", self.sfauser)
+        self.ec.set(node2, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node1, "gatewayUser", "nepi")
+        self.ec.set(node1, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node1, "cleanHome", True)
+        self.ec.set(node1, "cleanProcesses", True)
+
+        wnode_rm2 = self.ec.get_resource(node2)
+        api2 = wnode_rm2.sfaapi
+        self.assertEquals(api1, api2)
+
+        wnode_rm1.sfaapi._reserved = set()
+        wnode_rm1.sfaapi._blacklist = set()
+    
+    @skipIfNotSfi
+    def test_discover(self):
+        """
+        Check that the method do_discover reserve the right node.
+        """
+        node1 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node1, "hostname", "zotacB5")
+        self.ec.set(node1, "slicename", self.slicename)
+        self.ec.set(node1, "sfauser", self.sfauser)
+        self.ec.set(node1, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node1, "gatewayUser", "nepi")
+        self.ec.set(node1, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node1, "cleanHome", True)
+        self.ec.set(node1, "cleanProcesses", True)
+
+        wnode_rm = self.ec.get_resource(node1)
+       
+        hostname = wnode_rm.get("hostname")
+        self.assertIsNotNone(hostname)
+
+        self.assertEquals(wnode_rm.sfaapi._reserved, set())
+
+        wnode_rm.do_discover()
+        self.assertEquals(len(wnode_rm.sfaapi._reserved), 1)
+        self.assertEquals(wnode_rm._node_to_provision, 'wilab2.ilabt.iminds.be.zotacB5')
+
+        wnode_rm.sfaapi._reserved = set()
+        wnode_rm.sfaapi._blacklist = set()
+
+    @skipIfNotSfi
+    def test_provision(self):
+        """
+        This test checks that the method do_provision add the node in the slice and check
+        its well functioning.
+        """
+        node = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node, "hostname", "zotacB5")
+        self.ec.set(node, "slicename", self.slicename)
+        self.ec.set(node, "sfauser", self.sfauser)
+        self.ec.set(node, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node, "gatewayUser", "nepi")
+        self.ec.set(node, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node, "cleanHome", True)
+        self.ec.set(node, "cleanProcesses", True)
+
+        wnode_rm = self.ec.get_resource(node)
+
+        self.assertEquals(wnode_rm.sfaapi._reserved, set())
+        self.assertIsNone(wnode_rm._node_to_provision)
+
+        wnode_rm.do_discover()
+        with self.assertRaises(RuntimeError):
+            wnode_rm.do_provision()
+
+        if not self.ec.abort and self.ec.state(node) > 2:
+            cmd = 'echo "IT WORKED"'
+            ((out, err), proc) = wnode_rm.execute(cmd)
+            self.assertEquals(out.strip(), "IT WORKED")
+
+        wnode_rm.sfaapi._reserved = set()
+        wnode_rm.sfaapi._blacklist = set()
+
+        self.ec.shutdown()
+
+    @skipIfNotSfi
+    def test_xdeploy1(self):
+        """
+        Test deploy 1 node.
+        """
+        node = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node, "hostname", "zotacM20")
+        self.ec.set(node, "slicename", self.slicename)
+        self.ec.set(node, "sfauser", self.sfauser)
+        self.ec.set(node, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node, "gatewayUser", "nepi")
+        self.ec.set(node, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node, "cleanHome", True)
+        self.ec.set(node, "cleanProcesses", True)
+
+        self.ec.deploy()
+        self.ec.wait_deployed(node)
+        state = self.ec.state(node)
+        if not self.ec.abort:
+            self.assertIn(state, (3, 4))
+
+        wnode_rm = self.ec.get_resource(node)
+        wnode_rm.sfaapi._reserved = set()
+        wnode_rm.sfaapi._blacklist = set()
+
+        self.ec.shutdown()
+
+    @skipIfNotSfi
+    def test_xdeploy2(self):
+        """
+        Test deploy 2 nodes.
+        """
+        node1 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node1, "hostname", "zotacB5")
+        self.ec.set(node1, "slicename", self.slicename)
+        self.ec.set(node1, "sfauser", self.sfauser)
+        self.ec.set(node1, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node1, "gatewayUser", "nepi")
+        self.ec.set(node1, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node1, "cleanHome", True)
+        self.ec.set(node1, "cleanProcesses", True)
+
+        node2 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node2, "hostname", "zotacM20")
+        self.ec.set(node2, "slicename", self.slicename)
+        self.ec.set(node2, "sfauser", self.sfauser)
+        self.ec.set(node2, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node2, "gatewayUser", "nepi")
+        self.ec.set(node2, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node2, "cleanHome", True)
+        self.ec.set(node2, "cleanProcesses", True)
+
+        self.ec.deploy()
+        self.ec.wait_deployed([node1, node2])
+        state1 = self.ec.state(node1)
+        state2 = self.ec.state(node2)
+        if not self.ec.abort:
+            self.assertIn(state1, (3, 4))
+            self.assertIn(state2, (3, 4))
+
+        wnode_rm = self.ec.get_resource(node1)
+        wnode_rm.sfaapi._reserved = set()
+        wnode_rm.sfaapi._blacklist = set()
+
+        self.ec.shutdown()
+
+    @skipIfNotSfi
+    def test_xdeploy3(self):
+        """
+        Test deploy 2 nodes, already in the slice.
+        """
+        node1 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node1, "hostname", "zotacM20")
+        self.ec.set(node1, "slicename", self.slicename)
+        self.ec.set(node1, "sfauser", self.sfauser)
+        self.ec.set(node1, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node1, "gatewayUser", "nepi")
+        self.ec.set(node1, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node1, "cleanHome", True)
+        self.ec.set(node1, "cleanProcesses", True)
+
+        node2 = self.ec.register_resource("WilabtSfaNode")
+        self.ec.set(node2, "hostname", "zotacB5")
+        self.ec.set(node2, "slicename", self.slicename)
+        self.ec.set(node2, "sfauser", self.sfauser)
+        self.ec.set(node2, "sfaPrivateKey", self.sfaPrivateKey)
+        self.ec.set(node2, "gatewayUser", "nepi")
+        self.ec.set(node2, "gateway", "bastion.test.iminds.be")
+        self.ec.set(node2, "cleanHome", True)
+        self.ec.set(node2, "cleanProcesses", True)
+
+        self.ec.deploy()
+        self.ec.wait_deployed([node1, node2])
+        state1 = self.ec.state(node1)
+        state2 = self.ec.state(node2)
+        if not self.ec.abort:
+            self.assertEquals(state1, (3, 4))
+            self.assertEquals(state2, (3, 4))
+
+        self.ec.shutdown() 
+
+    def tearDown(self):
+        pass
+        #self.ec.shutdown()
+
+
+if __name__ == '__main__':
+    unittest.main()
+
+
+
index cd6e6bb..691e84d 100755 (executable)
@@ -38,7 +38,7 @@ class PLSfaNodeFactoryTestCase(unittest.TestCase):
 
     def test_creation_phase(self):
         self.assertEquals(PlanetlabSfaNode._rtype, "PlanetlabSfaNode")
-        self.assertEquals(len(PlanetlabSfaNode._attributes), 29)
+        self.assertEquals(len(PlanetlabSfaNode._attributes), 31)
 
 class PLSfaNodeTestCase(unittest.TestCase):
     """
@@ -73,8 +73,8 @@ class PLSfaNodeTestCase(unittest.TestCase):
 
         api1 = plnode_rm1.sfaapi
         self.assertIsInstance(api1, SFAAPI)
-        self.assertEquals(len(api1.reserved()), 0)
-        self.assertEquals(len(api1.blacklisted()), 0)
+        self.assertEquals(len(api1._reserved), 0)
+        self.assertEquals(len(api1._blacklist), 0)
 
         node2 = self.ec.register_resource("PlanetlabSfaNode")
         self.ec.set(node2, "hostname", "planetlab2.ionio.gr")
@@ -92,7 +92,7 @@ class PLSfaNodeTestCase(unittest.TestCase):
         Check that the method do_discover reserve the right node.
         """
         node = self.ec.register_resource("PlanetlabSfaNode")
-        self.ec.set(node, "hostname", "planetlab2.ionio.gr")
+        self.ec.set(node, "hostname", "roti.mimuw.edu.pl")
         self.ec.set(node, "username", self.username)
         self.ec.set(node, "sfauser", self.sfauser)
         self.ec.set(node, "sfaPrivateKey", self.sfaPrivateKey)
@@ -102,11 +102,14 @@ class PLSfaNodeTestCase(unittest.TestCase):
         hostname = plnode_rm.get("hostname")
         self.assertIsNotNone(hostname)
 
-        self.assertEquals(plnode_rm.sfaapi.reserved(), set())
+        self.assertEquals(len(plnode_rm.sfaapi._reserved), 0)
 
         plnode_rm.do_discover()
-        self.assertEquals(plnode_rm.sfaapi.reserved().pop(), 'ple.dbislab.planetlab2.ionio.gr')
-        self.assertEquals(plnode_rm._node_to_provision, 'ple.dbislab.planetlab2.ionio.gr')
+
+        self.assertEquals(len(plnode_rm.sfaapi._reserved), 1)
+        self.assertEquals(plnode_rm._node_to_provision, 'ple.mimuw.roti.mimuw.edu.pl')
+        plnode_rm.sfaapi._reserved = set()
+        plnode_rm.sfaapi._blacklist = set()
 
     @skipIfNotSfaCredentials
     def test_provision(self):
@@ -122,11 +125,9 @@ class PLSfaNodeTestCase(unittest.TestCase):
 
         plnode_rm = self.ec.get_resource(node)
 
-        self.assertEquals(plnode_rm.sfaapi.reserved(), set())
+        self.assertEquals(plnode_rm.sfaapi._reserved, set())
         self.assertIsNone(plnode_rm._node_to_provision)
 
-        slicename = 'ple.' + self.username.replace('_', '.')
-
         plnode_rm.do_discover()
         plnode_rm.do_provision()    
 
@@ -134,20 +135,13 @@ class PLSfaNodeTestCase(unittest.TestCase):
         ((out, err), proc) = plnode_rm.execute(cmd)
         self.assertEquals(out.strip(), "IT WORKED")
 
-        urn_to_delete = 'urn:publicid:IDN+ple:dbislab+node+planetlab2.ionio.gr'
-        plnode_rm.sfaapi.remove_resource_from_slice(slicename, urn_to_delete)
-
-        slice_resources = plnode_rm.sfaapi.get_slice_resources(slicename)['resource']
-        if slice_resources:
-            slice_resources_hrn = plnode_rm.sfaapi.get_resources_hrn(slice_resources)
-            self.assertNotIn('planetlab2.ionio.gr', slice_resources_hrn.keys())           
+        plnode_rm.sfaapi._reserved = set()
+        plnode_rm.sfaapi._blacklist = set()
 
     @skipIfNotSfaCredentials
-    def test_xdeploy(self):
+    def test_xdeploy1(self):
         """
-        Test with the nodes being discover and provision at the same time.
-        The deploy should fail as the test before, there aren't 4 nodes of 
-        that carachteristics.
+        Test deploy 1 node.
         """
         node = self.ec.register_resource("PlanetlabSfaNode")
         self.ec.set(node, "hostname", "planetlab2.ionio.gr")
@@ -158,7 +152,70 @@ class PLSfaNodeTestCase(unittest.TestCase):
         self.ec.deploy()
         self.ec.wait_deployed(node)
         state = self.ec.state(node)
-        self.assertEquals(state, 3)
+        if not self.ec.abort:
+            self.assertIn(state, (3, 4))
+
+        plnode_rm = self.ec.get_resource(1)
+        plnode_rm.sfaapi._reserved = set()
+        plnode_rm.sfaapi._blacklist = set()
+
+    @skipIfNotSfaCredentials
+    def test_xdeploy2(self):
+        """
+        Test deploy 2 nodes. Empty slice.
+        """
+        node1 = self.ec.register_resource("PlanetlabSfaNode")
+        self.ec.set(node1, "hostname", "planetlab3.xeno.cl.cam.ac.uk")
+        self.ec.set(node1, "username", self.username)
+        self.ec.set(node1, "sfauser", self.sfauser)
+        self.ec.set(node1, "sfaPrivateKey", self.sfaPrivateKey)
+
+        node2 = self.ec.register_resource("PlanetlabSfaNode")
+        self.ec.set(node2, "hostname", "planetlab1.cs.vu.nl")
+        self.ec.set(node2, "username", self.username)
+        self.ec.set(node2, "sfauser", self.sfauser)
+        self.ec.set(node2, "sfaPrivateKey", self.sfaPrivateKey)
+
+        node1rm = self.ec.get_resource(node1)
+        node1rm._delete_from_slice()
+
+        self.ec.deploy()
+        self.ec.wait_deployed([node1, node2])
+        state1 = self.ec.state(node1)
+        state2 = self.ec.state(node2)
+        if not self.ec.abort:
+            self.assertIn(state1, (3, 4))
+            self.assertIn(state2, (3, 4))
+
+        plnode_rm = self.ec.get_resource(1)
+        plnode_rm.sfaapi._reserved = set()
+        plnode_rm.sfaapi._blacklist = set()
+
+    @skipIfNotSfaCredentials
+    def test_xdeploy3(self):
+        """
+        Test deploy 2 nodes, already in the slice.
+        """
+        node1 = self.ec.register_resource("PlanetlabSfaNode")
+        self.ec.set(node1, "hostname", "planetlab3.xeno.cl.cam.ac.uk")
+        self.ec.set(node1, "username", self.username)
+        self.ec.set(node1, "sfauser", self.sfauser)
+        self.ec.set(node1, "sfaPrivateKey", self.sfaPrivateKey)
+
+        node2 = self.ec.register_resource("PlanetlabSfaNode")
+        self.ec.set(node2, "hostname", "planetlab1.cs.vu.nl")
+        self.ec.set(node2, "username", self.username)
+        self.ec.set(node2, "sfauser", self.sfauser)
+        self.ec.set(node2, "sfaPrivateKey", self.sfaPrivateKey)
+
+        self.ec.deploy()
+        self.ec.wait_deployed([node1, node2])
+        state1 = self.ec.state(node1)
+        state2 = self.ec.state(node2)
+        if not self.ec.abort:
+            self.assertIn(state1, (3, 4))
+            self.assertIn(state2, (3, 4))
+
 
     def tearDown(self):
         self.ec.shutdown()