Revision 6e168615 snf-tools/synnefo_tools/burnin.py

b/snf-tools/synnefo_tools/burnin.py
35 35

  
36 36
"""Perform integration testing on a running Synnefo deployment"""
37 37

  
38
import __main__
38
#import __main__
39 39
import datetime
40 40
import inspect
41 41
import logging
......
58 58
from kamaki.clients.image import ImageClient
59 59
from kamaki.clients import ClientError
60 60

  
61
from fabric.api import *
61
import fabric.api as fabric
62 62

  
63 63
from vncauthproxy.d3des import generate_response as d3des_generate_response
64 64

  
......
70 70
        raise Exception("The unittest2 package is required for Python < 2.7")
71 71
    import unittest
72 72

  
73
# --------------------------------------------------------------------
74
# Global Variables
75
API = None
76
TOKEN = None
77
PLANKTON = None
78
PLANKTON_USER = None
79
NO_IPV6 = None
80
DEFAULT_API = "https://cyclades.okeanos.grnet.gr/api/v1.1"
81
DEFAULT_PLANKTON = "https://cyclades.okeanos.grnet.gr/plankton"
82
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
83
NOFAILFAST = None
84
VERBOSE = None
85

  
86
# A unique id identifying this test run
87
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
88
                                         "%Y%m%d%H%M%S")
89
SNF_TEST_PREFIX = "snf-test-"
90

  
91
red = '\x1b[31m'
92
yellow = '\x1b[33m'
93
green = '\x1b[32m'
94
normal = '\x1b[0m'
95

  
73 96

  
97
# --------------------------------------------------------------------
98
# BurninTestReulst class
74 99
class BurninTestResult(unittest.TextTestResult):
75 100
    def addSuccess(self, test):
76 101
        super(BurninTestResult, self).addSuccess(test)
......
85 110

  
86 111
        elif self.dots:
87 112
            self.stream.write('.')
88
            self.stream.flush() 
89
            
113
            self.stream.flush()
114

  
90 115
    def addError(self, test, err):
91 116
        super(BurninTestResult, self).addError(test, err)
92 117
        if self.showAll:
......
120 145
            self.stream.flush()
121 146

  
122 147

  
123

  
124
API = None
125
TOKEN = None
126
DEFAULT_API = "https://cyclades.okeanos.grnet.gr/api/v1.1"
127
DEFAULT_PLANKTON = "https://cyclades.okeanos.grnet.gr/plankton"
128
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
129

  
130
# A unique id identifying this test run
131
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
132
                                         "%Y%m%d%H%M%S")
133
SNF_TEST_PREFIX = "snf-test-"
134

  
135
red = '\x1b[31m'
136
yellow = '\x1b[33m'
137
green = '\x1b[32m'
138
normal = '\x1b[0m'
139

  
148
# --------------------------------------------------------------------
149
# Format Results
140 150
class burninFormatter(logging.Formatter):
141

  
142 151
    err_fmt = red + "ERROR: %(msg)s" + normal
143 152
    dbg_fmt = green + "* %(msg)s" + normal
144 153
    info_fmt = "%(msg)s"
......
147 156
        logging.Formatter.__init__(self, fmt)
148 157

  
149 158
    def format(self, record):
150

  
151 159
        format_orig = self._fmt
152

  
153 160
        # Replace the original format with one customized by logging level
154 161
        if record.levelno == 10:    # DEBUG
155 162
            self._fmt = burninFormatter.dbg_fmt
156

  
157 163
        elif record.levelno == 20:  # INFO
158 164
            self._fmt = burninFormatter.info_fmt
159

  
160 165
        elif record.levelno == 40:  # ERROR
161 166
            self._fmt = burninFormatter.err_fmt
162

  
163 167
        result = logging.Formatter.format(self, record)
164 168
        self._fmt = format_orig
165

  
166 169
        return result
167 170

  
168 171
log = logging.getLogger("burnin")
......
172 175
log.addHandler(handler)
173 176

  
174 177

  
178
# --------------------------------------------------------------------
179
# UnauthorizedTestCase class
175 180
class UnauthorizedTestCase(unittest.TestCase):
176

  
181
    """Test unauthorized access"""
177 182
    @classmethod
178 183
    def setUpClass(cls):
179 184
        cls.result_dict = dict()
......
181 186
    def test_unauthorized_access(self):
182 187
        """Test access without a valid token fails"""
183 188
        log.info("Authentication test")
184

  
185 189
        falseToken = '12345'
186 190
        c = ComputeClient(API, falseToken)
187 191

  
......
190 194
            self.assertEqual(cm.exception.status, 401)
191 195

  
192 196

  
197
# --------------------------------------------------------------------
198
# ImagesTestCase class
193 199
class ImagesTestCase(unittest.TestCase):
194 200
    """Test image lists for consistency"""
195 201
    @classmethod
196 202
    def setUpClass(cls):
197 203
        """Initialize kamaki, get (detailed) list of images"""
198 204
        log.info("Getting simple and detailed list of images")
199

  
200 205
        cls.client = ComputeClient(API, TOKEN)
201 206
        cls.plankton = ImageClient(PLANKTON, TOKEN)
202 207
        cls.images = cls.plankton.list_public()
......
232 237
            self.assertTrue(keys.issubset(i["metadata"]["values"].keys()))
233 238

  
234 239

  
240
# --------------------------------------------------------------------
241
# FlavorsTestCase class
235 242
class FlavorsTestCase(unittest.TestCase):
236 243
    """Test flavor lists for consistency"""
237 244
    @classmethod
238 245
    def setUpClass(cls):
239 246
        """Initialize kamaki, get (detailed) list of flavors"""
240 247
        log.info("Getting simple and detailed list of flavors")
241

  
242 248
        cls.client = ComputeClient(API, TOKEN)
243 249
        cls.flavors = cls.client.list_flavors()
244 250
        cls.dflavors = cls.client.list_flavors(detail=True)
......
265 271

  
266 272
    def test_005_well_formed_flavor_names(self):
267 273
        """Test flavors have names of the form CxxRyyDzz
268

  
269 274
        Where xx is vCPU count, yy is RAM in MiB, zz is Disk in GiB
270

  
271 275
        """
272 276
        for f in self.dflavors:
273 277
            self.assertEqual("C%dR%dD%d" % (f["cpu"], f["ram"], f["disk"]),
......
275 279
                             "Flavor %s does not match its specs." % f["name"])
276 280

  
277 281

  
282
# --------------------------------------------------------------------
283
# ServersTestCase class
278 284
class ServersTestCase(unittest.TestCase):
279 285
    """Test server lists for consistency"""
280 286
    @classmethod
......
309 315
    @classmethod
310 316
    def setUpClass(cls):
311 317
        """Initialize a kamaki instance"""
312
        log.info("Spawning server for image `%s'" %cls.imagename)
318
        log.info("Spawning server for image `%s'" % cls.imagename)
313 319
        cls.client = ComputeClient(API, TOKEN)
314 320
        cls.cyclades = CycladesClient(API, TOKEN)
315 321
        cls.result_dict = dict()
......
321 327

  
322 328
        for nic in nics:
323 329
            net_id = nic["network_id"]
324
            if self.cyclades.get_network_details(net_id)["public"] == True:
330
            if self.cyclades.get_network_details(net_id)["public"]:
325 331
                public_addrs = nic["ipv4"]
326
        
327
        self.assertTrue(public_addrs != None)
332

  
333
        self.assertTrue(public_addrs is not None)
328 334

  
329 335
        return public_addrs
330 336

  
......
335 341

  
336 342
        for nic in nics:
337 343
            net_id = nic["network_id"]
338
            if self.cyclades.get_network_details(net_id)["public"] == True:
344
            if self.cyclades.get_network_details(net_id)["public"]:
339 345
                public_addrs = nic["ipv6"]
340
        
341
        self.assertTrue(public_addrs != None)
342 346

  
343
        return public_addrs
347
        self.assertTrue(public_addrs is not None)
344 348

  
349
        return public_addrs
345 350

  
346
    def _connect_loginname(self, os):
351
    def _connect_loginname(self, os_value):
347 352
        """Return the login name for connections based on the server OS"""
348
        if os in ("Ubuntu", "Kubuntu", "Fedora"):
353
        if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
349 354
            return "user"
350
        elif os in ("windows", "windows_alpha1"):
355
        elif os_value in ("windows", "windows_alpha1"):
351 356
            return "Administrator"
352 357
        else:
353 358
            return "root"
......
368 373
            af, socktype, proto, canonname, sa = res
369 374
            try:
370 375
                sock = socket.socket(af, socktype, proto)
371
            except socket.error as msg:
376
            except socket.error:
372 377
                sock = None
373 378
                continue
374 379
            try:
375 380
                sock.connect(sa)
376
            except socket.error as msg:
381
            except socket.error:
377 382
                sock.close()
378 383
                sock = None
379 384
                continue
......
426 431
        msg = "connect over %s to %s:%s" % \
427 432
              (familystr.get(family, "Unknown"), host, port)
428 433
        sock = self._try_until_timeout_expires(
429
                self.action_timeout, self.action_timeout,
430
                msg, self._get_connected_tcp_socket,
431
                family, host, port)
434
            self.action_timeout, self.action_timeout,
435
            msg, self._get_connected_tcp_socket,
436
            family, host, port)
432 437
        return sock
433 438

  
434 439
    def _insist_on_status_transition(self, current_status, new_status,
435
                                    fail_timeout, warn_timeout=None):
440
                                     fail_timeout, warn_timeout=None):
436 441
        msg = "Server %d: `%s', waiting for %s -> %s" % \
437 442
              (self.serverid, self.servername, current_status, new_status)
438 443
        if warn_timeout is None:
......
447 452
    def _insist_on_ssh_hostname(self, hostip, username, password):
448 453
        msg = "SSH to %s, as %s/%s" % (hostip, username, password)
449 454
        hostname = self._try_until_timeout_expires(
450
                self.action_timeout, self.action_timeout,
451
                msg, self._get_hostname_over_ssh,
452
                hostip, username, password)
455
            self.action_timeout, self.action_timeout,
456
            msg, self._get_hostname_over_ssh,
457
            hostip, username, password)
453 458

  
454 459
        # The hostname must be of the form 'prefix-id'
455 460
        self.assertTrue(hostname.endswith("-%d\n" % self.serverid))
......
539 544
        log.info("Creating server metadata")
540 545

  
541 546
        image = self.client.get_image_details(self.imageid)
542
        os = image["metadata"]["values"]["os"]
547
        os_value = image["metadata"]["values"]["os"]
543 548
        users = image["metadata"]["values"].get("users", None)
544
        self.client.update_server_metadata(self.serverid, OS=os)
549
        self.client.update_server_metadata(self.serverid, OS=os_value)
545 550

  
546 551
        userlist = users.split()
547 552

  
......
551 556

  
552 557
        if "root" in userlist:
553 558
            cls.username = "root"
554
        elif users == None:
555
            cls.username = self._connect_loginname(os)
559
        elif users is None:
560
            cls.username = self._connect_loginname(os_value)
556 561
        else:
557 562
            cls.username = choice(userlist)
558 563

  
......
573 578

  
574 579
        log.info("Waiting for server to become ACTIVE")
575 580

  
576
        self._insist_on_status_transition("BUILD", "ACTIVE",
577
                                         self.build_fail, self.build_warning)
581
        self._insist_on_status_transition(
582
            "BUILD", "ACTIVE", self.build_fail, self.build_warning)
578 583

  
579 584
    def test_003a_get_server_oob_console(self):
580 585
        """Test getting OOB server console over VNC
......
585 590
        """
586 591
        console = self.cyclades.get_server_console(self.serverid)
587 592
        self.assertEquals(console['type'], "vnc")
588
        sock = self._insist_on_tcp_connection(socket.AF_INET,
589
                                        console["host"], console["port"])
593
        sock = self._insist_on_tcp_connection(
594
            socket.AF_INET, console["host"], console["port"])
590 595

  
591 596
        # Step 1. ProtocolVersion message (par. 6.1.1)
592 597
        version = sock.recv(1024)
......
619 624

  
620 625
        log.info("Validate server's IPv4")
621 626

  
622

  
623 627
        server = self.client.get_server_details(self.serverid)
624 628
        ipv4 = self._get_ipv4(server)
625 629

  
......
680 684
        """Test server becomes STOPPED"""
681 685

  
682 686
        log.info("Waiting until server becomes STOPPED")
683
        self._insist_on_status_transition("ACTIVE", "STOPPED",
684
                                         self.action_timeout,
685
                                         self.action_timeout)
687
        self._insist_on_status_transition(
688
            "ACTIVE", "STOPPED", self.action_timeout, self.action_timeout)
686 689

  
687 690
    def test_010_submit_start_request(self):
688 691
        """Test submit start server request"""
......
695 698
        """Test server becomes ACTIVE again"""
696 699

  
697 700
        log.info("Waiting until server becomes ACTIVE")
698
        self._insist_on_status_transition("STOPPED", "ACTIVE",
699
                                         self.action_timeout,
700
                                         self.action_timeout)
701
        self._insist_on_status_transition(
702
            "STOPPED", "ACTIVE", self.action_timeout, self.action_timeout)
701 703

  
702 704
    def test_011a_server_responds_to_ping_IPv4(self):
703 705
        """Test server OS is actually up and running again"""
......
728 730
        self._skipIf(not self.is_windows, "only valid for Windows servers")
729 731
        server = self.client.get_server_details(self.serverid)
730 732
        ipv4 = self._get_ipv4(server)
731
        sock = _insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
733
        sock = self._insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
732 734

  
733 735
        # No actual RDP processing done. We assume the RDP server is there
734 736
        # if the connection to the RDP port is successful.
......
742 744

  
743 745
        server = self.client.get_server_details(self.serverid)
744 746
        ipv6 = self._get_ipv6(server)
745
        sock = _get_tcp_connection(socket.AF_INET6, ipv6, 3389)
747
        sock = self._get_tcp_connection(socket.AF_INET6, ipv6, 3389)
746 748

  
747 749
        # No actual RDP processing done. We assume the RDP server is there
748 750
        # if the connection to the RDP port is successful.
......
751 753
    def test_016_personality_is_enforced(self):
752 754
        """Test file injection for personality enforcement"""
753 755
        self._skipIf(self.is_windows, "only implemented for Linux servers")
754
        self._skipIf(self.personality == None, "No personality file selected")
756
        self._skipIf(self.personality is None, "No personality file selected")
755 757

  
756 758
        log.info("Trying to inject file for personality enforcement")
757 759

  
......
777 779

  
778 780
        log.info("Testing if server becomes DELETED")
779 781

  
780
        self._insist_on_status_transition("ACTIVE", "DELETED",
781
                                         self.action_timeout,
782
                                         self.action_timeout)
782
        self._insist_on_status_transition(
783
            "ACTIVE", "DELETED", self.action_timeout, self.action_timeout)
783 784

  
784 785
    def test_019_server_no_longer_in_server_list(self):
785 786
        """Test server is no longer in server list"""
......
823 824

  
824 825
        for nic in nics:
825 826
            net_id = nic["network_id"]
826
            if self.client.get_network_details(net_id)["public"] == True:
827
            if self.client.get_network_details(net_id)["public"]:
827 828
                public_addrs = nic["ipv4"]
828
        
829
        self.assertTrue(public_addrs != None)
830 829

  
831
        return public_addrs
830
        self.assertTrue(public_addrs is not None)
832 831

  
832
        return public_addrs
833 833

  
834
    def _connect_loginname(self, os):
834
    def _connect_loginname(self, os_value):
835 835
        """Return the login name for connections based on the server OS"""
836
        if os in ("Ubuntu", "Kubuntu", "Fedora"):
836
        if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
837 837
            return "user"
838
        elif os in ("windows", "windows_alpha1"):
838
        elif os_value in ("windows", "windows_alpha1"):
839 839
            return "Administrator"
840 840
        else:
841 841
            return "root"
......
874 874

  
875 875
        self.result_dict["Server A ID"] = str(serverA["id"])
876 876
        self.result_dict["Server A password"] = serverA["adminPass"]
877
        
877

  
878 878
    def test_00001b_serverA_becomes_active(self):
879 879
        """Test server becomes ACTIVE"""
880 880

  
......
899 899
        """Test submit create server request"""
900 900

  
901 901
        log.info("Creating test server B")
902
        
902

  
903 903
        serverB = self.client.create_server(self.servername, self.flavorid,
904 904
                                            self.imageid, personality=None)
905 905

  
......
945 945

  
946 946
        log.info("Submit new network request")
947 947
        self.result_dict.clear()
948
                
948

  
949 949
        name = SNF_TEST_PREFIX + TEST_RUN_ID
950
        previous_num = len(self.client.list_networks())
951
        network = self.client.create_network(name,cidr='10.0.0.1/28')
950
        #previous_num = len(self.client.list_networks())
951
        network = self.client.create_network(name, cidr='10.0.0.1/28')
952 952

  
953 953
        #Test if right name is assigned
954 954
        self.assertEqual(network['name'], name)
......
956 956
        # Update class attributes
957 957
        cls = type(self)
958 958
        cls.networkid = network['id']
959
        networks = self.client.list_networks()
959
        #networks = self.client.list_networks()
960 960

  
961 961
        fail_tmout = time.time() + self.action_timeout
962 962

  
......
990 990

  
991 991
        while True:
992 992

  
993
            netsA = [x['network_id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
994
            netsB = [x['network_id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
993
            netsA = [x['network_id']
994
                     for x in self.client.get_server_details(
995
                         self.serverid['A'])['attachments']['values']]
996
            netsB = [x['network_id']
997
                     for x in self.client.get_server_details(
998
                         self.serverid['B'])['attachments']['values']]
995 999

  
996 1000
            if (self.networkid in netsA) and (self.networkid in netsB):
997 1001
                conn_exists = True
......
1000 1004
                self.assertLess(time.time(), fail_tmout)
1001 1005
            else:
1002 1006
                time.sleep(self.query_interval)
1003
                
1007

  
1004 1008
        #Adding private IPs to class attributes
1005 1009
        cls = type(self)
1006 1010
        cls.priv_ip = dict()
1007 1011

  
1008
        nicsA = self.client.get_server_details(self.serverid['A'])['attachments']['values']
1009
        nicsB = self.client.get_server_details(self.serverid['B'])['attachments']['values']
1012
        nicsA = self.client.get_server_details(
1013
            self.serverid['A'])['attachments']['values']
1014
        nicsB = self.client.get_server_details(
1015
            self.serverid['B'])['attachments']['values']
1010 1016

  
1011 1017
        if conn_exists:
1012 1018
            for nic in nicsA:
......
1064 1070
        fail_tmout = time.time() + self.action_timeout
1065 1071

  
1066 1072
        s = False
1067
        
1073

  
1068 1074
        self.result_dict["Server A public IP"] = str(ip)
1069 1075

  
1070 1076
        while True:
......
1120 1126

  
1121 1127
        log.info("Testing if server B responds to IPv4 pings")
1122 1128
        self.result_dict.clear()
1123
        
1129

  
1124 1130
        server = self.client.get_server_details(self.serverid['B'])
1125 1131
        ip = self._get_ipv4(server)
1126 1132

  
......
1153 1159

  
1154 1160
        server = self.client.get_server_details(self.serverid['A'])
1155 1161
        image = self.client.get_image_details(self.imageid)
1156
        os = image['metadata']['values']['os']
1162
        os_value = image['metadata']['values']['os']
1157 1163

  
1158 1164
        users = image["metadata"]["values"].get("users", None)
1159 1165
        userlist = users.split()
1160 1166

  
1161 1167
        if "root" in userlist:
1162 1168
            loginname = "root"
1163
        elif users == None:
1164
            loginname = self._connect_loginname(os)
1169
        elif users is None:
1170
            loginname = self._connect_loginname(os_value)
1165 1171
        else:
1166 1172
            loginname = choice(userlist)
1167 1173

  
......
1173 1179
        res = False
1174 1180

  
1175 1181
        if loginname != "root":
1176
            with settings(
1177
                hide('warnings', 'running'),
1178
                warn_only=True,
1179
                host_string=hostip,
1180
                user=loginname, password=myPass
1181
                ):
1182

  
1183
                if len(sudo('ifconfig eth1 %s' % self.priv_ip["A"])) == 0:
1182
            with fabric.settings(
1183
                    fabric.hide('warnings', 'running'),
1184
                    warn_only=True,
1185
                    host_string=hostip,
1186
                    user=loginname, password=myPass):
1187
                conf_res = fabric.sudo('ifconfig eth1 %s' % self.priv_ip["A"])
1188
                if len(conf_res) == 0:
1184 1189
                    res = True
1185 1190

  
1186 1191
        else:
1187
            with settings(
1188
                hide('warnings', 'running'),
1189
                warn_only=True,
1190
                host_string=hostip,
1191
                user=loginname, password=myPass
1192
                ):
1193

  
1194
                if len(run('ifconfig eth1 %s' % self.priv_ip["A"])) == 0:
1192
            with fabric.settings(
1193
                    fabric.hide('warnings', 'running'),
1194
                    warn_only=True,
1195
                    host_string=hostip,
1196
                    user=loginname, password=myPass):
1197
                conf_res = fabric.run('ifconfig eth1 %s' % self.priv_ip["A"])
1198
                if len(conf_res) == 0:
1195 1199
                    res = True
1196 1200

  
1197 1201
        self.assertTrue(res)
......
1205 1209

  
1206 1210
        server = self.client.get_server_details(self.serverid['B'])
1207 1211
        image = self.client.get_image_details(self.imageid)
1208
        os = image['metadata']['values']['os']
1212
        os_value = image['metadata']['values']['os']
1209 1213

  
1210 1214
        users = image["metadata"]["values"].get("users", None)
1211 1215
        userlist = users.split()
1212 1216

  
1213 1217
        if "root" in userlist:
1214 1218
            loginname = "root"
1215
        elif users == None:
1216
            loginname = self._connect_loginname(os)
1219
        elif users is None:
1220
            loginname = self._connect_loginname(os_value)
1217 1221
        else:
1218 1222
            loginname = choice(userlist)
1219 1223

  
......
1225 1229
        res = False
1226 1230

  
1227 1231
        if loginname != "root":
1228
            with settings(
1229
                hide('warnings', 'running'),
1230
                warn_only=True,
1231
                host_string=hostip,
1232
                user=loginname, password=myPass
1233
                ):
1234

  
1235
                if len(sudo('ifconfig eth1 %s' % self.priv_ip["B"])) == 0:
1232
            with fabric.settings(
1233
                    fabric.hide('warnings', 'running'),
1234
                    warn_only=True,
1235
                    host_string=hostip,
1236
                    user=loginname, password=myPass):
1237
                conf_res = fabric.sudo('ifconfig eth1 %s' % self.priv_ip["B"])
1238
                if len(conf_res) == 0:
1236 1239
                    res = True
1237 1240

  
1238 1241
        else:
1239
            with settings(
1240
                hide('warnings', 'running'),
1241
                warn_only=True,
1242
                host_string=hostip,
1243
                user=loginname, password=myPass
1244
                ):
1245

  
1246
                if len(run('ifconfig eth1 %s' % self.priv_ip["B"])) == 0:
1242
            with fabric.settings(
1243
                    fabric.hide('warnings', 'running'),
1244
                    warn_only=True,
1245
                    host_string=hostip,
1246
                    user=loginname, password=myPass):
1247
                conf_res = fabric.run('ifconfig eth1 %s' % self.priv_ip["B"])
1248
                if len(conf_res) == 0:
1247 1249
                    res = True
1248 1250

  
1249 1251
        self.assertTrue(res)
......
1257 1259

  
1258 1260
        server = self.client.get_server_details(self.serverid['A'])
1259 1261
        image = self.client.get_image_details(self.imageid)
1260
        os = image['metadata']['values']['os']
1262
        os_value = image['metadata']['values']['os']
1261 1263
        hostip = self._get_ipv4(server)
1262 1264

  
1263 1265
        users = image["metadata"]["values"].get("users", None)
......
1265 1267

  
1266 1268
        if "root" in userlist:
1267 1269
            loginname = "root"
1268
        elif users == None:
1269
            loginname = self._connect_loginname(os)
1270
        elif users is None:
1271
            loginname = self._connect_loginname(os_value)
1270 1272
        else:
1271 1273
            loginname = choice(userlist)
1272 1274

  
......
1298 1300

  
1299 1301
        prev_state = self.client.get_network_details(self.networkid)
1300 1302
        prev_nics = prev_state['attachments']['values']
1301
        prev_conn = len(prev_nics)
1303
        #prev_conn = len(prev_nics)
1302 1304

  
1303
        nicsA=[x['id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
1304
        nicsB=[x['id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
1305
        nicsA = [x['id']
1306
                 for x in self.client.get_server_details(
1307
                     self.serverid['A'])['attachments']['values']]
1308
        nicsB = [x['id']
1309
                 for x in self.client.get_server_details(
1310
                     self.serverid['B'])['attachments']['values']]
1305 1311

  
1306 1312
        for nic in prev_nics:
1307 1313
            if nic in nicsA:
......
1309 1315
            if nic in nicsB:
1310 1316
                self.client.disconnect_server(self.serverid['B'], nic)
1311 1317

  
1312

  
1313 1318
        #Insist on deleting until action timeout
1314 1319
        fail_tmout = time.time() + self.action_timeout
1315 1320

  
1316 1321
        while True:
1317

  
1318
            netsA=[x['network_id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
1319
            netsB=[x['network_id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
1320

  
1321

  
1322
            connected = (self.client.get_network_details(self.networkid))
1323
            connections = connected['attachments']['values']
1322
            netsA = [x['network_id']
1323
                     for x in self.client.get_server_details(
1324
                         self.serverid['A'])['attachments']['values']]
1325
            netsB = [x['network_id']
1326
                     for x in self.client.get_server_details(
1327
                         self.serverid['B'])['attachments']['values']]
1328

  
1329
            #connected = (self.client.get_network_details(self.networkid))
1330
            #connections = connected['attachments']['values']
1324 1331
            if (self.networkid not in netsA) and (self.networkid not in netsB):
1325 1332
                conn_exists = False
1326 1333
                break
......
1358 1365
            else:
1359 1366
                time.sleep(self.query_interval)
1360 1367

  
1361

  
1362

  
1363 1368
    def test_006_cleanup_servers(self):
1364 1369
        """Cleanup servers created for this test"""
1365 1370

  
......
1410 1415

  
1411 1416
        while True:
1412 1417
            multi.debug("I am process %d, GETting from queue is %s" %
1413
                     (os.getpid(), self.testq))
1418
                        (os.getpid(), self.testq))
1414 1419
            msg = self.testq.get()
1415 1420

  
1416 1421
            multi.debug("Dequeued msg: %s" % msg)
......
1433 1438
                                          TEST_RUN_ID + '.log')
1434 1439

  
1435 1440
                f = open(log_file, 'w')
1436
                fail = open(fail_file,'w')
1441
                fail = open(fail_file, 'w')
1437 1442
                error = open(error_file, 'w')
1438 1443

  
1439 1444
                log.info(yellow + '* Starting testcase: %s' % msg + normal)
1440 1445

  
1441
                runner = unittest.TextTestRunner(f, verbosity=2, failfast = True, resultclass=BurninTestResult)
1446
                runner = unittest.TextTestRunner(
1447
                    f, verbosity=2, failfast=True,
1448
                    resultclass=BurninTestResult)
1442 1449
                suite = unittest.TestLoader().loadTestsFromTestCase(msg)
1443 1450
                result = runner.run(suite)
1444 1451

  
1445 1452
                for res in result.errors:
1446
                    log.error("snf-burnin encountered an error in " \
1447
                                  "testcase: %s" %msg)
1453
                    log.error("snf-burnin encountered an error in "
1454
                              "testcase: %s" % msg)
1448 1455
                    log.error("See log for details")
1449 1456
                    error.write(str(res[0]) + '\n')
1450 1457
                    error.write(str(res[0].shortDescription()) + '\n')
1451 1458
                    error.write('\n')
1452 1459

  
1453 1460
                for res in result.failures:
1454
                    log.error("snf-burnin failed in testcase: %s" %msg)
1461
                    log.error("snf-burnin failed in testcase: %s" % msg)
1455 1462
                    log.error("See log for details")
1456 1463
                    fail.write(str(res[0]) + '\n')
1457 1464
                    fail.write(str(res[0].shortDescription()) + '\n')
1458 1465
                    fail.write('\n')
1459
                    if NOFAILFAST == False:
1466
                    if not NOFAILFAST:
1460 1467
                        sys.exit()
1461 1468

  
1462 1469
                if (len(result.failures) == 0) and (len(result.errors) == 0):
1463
                    log.debug("Passed testcase: %s" %msg)
1470
                    log.debug("Passed testcase: %s" % msg)
1464 1471

  
1465 1472
                f.close()
1466 1473
                fail.close()
1467 1474
                error.close()
1468 1475

  
1469

  
1470 1476
            else:
1471 1477
                raise Exception("Cannot handle msg: %s" % msg)
1472 1478

  
1473
def _run_cases_in_series(cases,image_folder):
1479

  
1480
def _run_cases_in_series(cases, image_folder):
1474 1481
    """Run instances of TestCase in series"""
1475 1482

  
1476 1483
    for case in cases:
1477 1484

  
1478 1485
        test = case.__name__
1479 1486

  
1480
        log.info(yellow + '* Starting testcase: %s' %test + normal)
1487
        log.info(yellow + '* Starting testcase: %s' % test + normal)
1481 1488
        log_file = os.path.join(image_folder, 'details_' +
1482 1489
                                (case.__name__) + "_" +
1483 1490
                                TEST_RUN_ID + '.log')
......
1493 1500
        error = open(error_file, "w")
1494 1501

  
1495 1502
        suite = unittest.TestLoader().loadTestsFromTestCase(case)
1496
        runner = unittest.TextTestRunner(f, verbosity=2, failfast=True, resultclass=BurninTestResult)
1503
        runner = unittest.TextTestRunner(
1504
            f, verbosity=2, failfast=True,
1505
            resultclass=BurninTestResult)
1497 1506
        result = runner.run(suite)
1498 1507

  
1499 1508
        for res in result.errors:
1500
            log.error("snf-burnin encountered an error in " \
1501
                          "testcase: %s" %test)
1509
            log.error("snf-burnin encountered an error in "
1510
                      "testcase: %s" % test)
1502 1511
            log.error("See log for details")
1503 1512
            error.write(str(res[0]) + '\n')
1504 1513
            error.write(str(res[0].shortDescription()) + '\n')
1505 1514
            error.write('\n')
1506 1515

  
1507 1516
        for res in result.failures:
1508
            log.error("snf-burnin failed in testcase: %s" %test)
1517
            log.error("snf-burnin failed in testcase: %s" % test)
1509 1518
            log.error("See log for details")
1510 1519
            fail.write(str(res[0]) + '\n')
1511 1520
            fail.write(str(res[0].shortDescription()) + '\n')
1512 1521
            fail.write('\n')
1513
            if NOFAILFAST == False:
1522
            if not NOFAILFAST:
1514 1523
                sys.exit()
1515 1524

  
1516 1525
        if (len(result.failures) == 0) and (len(result.errors) == 0):
1517
                log.debug("Passed testcase: %s" %test)
1526
            log.debug("Passed testcase: %s" % test)
1518 1527

  
1519
    
1520 1528

  
1521 1529
def _run_cases_in_parallel(cases, fanout, image_folder):
1522 1530
    """Run instances of TestCase in parallel, in a number of distinct processes
......
1543 1551
    worker_folder = []
1544 1552
    runners = []
1545 1553

  
1546
    for i in xrange(0,fanout):
1554
    for i in xrange(0, fanout):
1547 1555
        testq.append(Queue())
1548 1556
        worker_folder.append(os.path.join(image_folder, 'process'+str(i)))
1549 1557
        os.mkdir(worker_folder[i])
......
1552 1560
        kwargs = dict(testq=testq[i], worker_folder=worker_folder[i])
1553 1561
        runners.append(TestRunnerProcess(kwargs=kwargs))
1554 1562

  
1555
    multi.debug("Spawning %d test runner processes" %len(runners))
1563
    multi.debug("Spawning %d test runner processes" % len(runners))
1556 1564

  
1557 1565
    for p in runners:
1558 1566
        p.start()
......
1563 1571
        testq[i].put("TEST_RUNNER_TERMINATE")
1564 1572

  
1565 1573
    multi.debug("Spawned %d test runners, PIDs are %s" %
1566
              (len(runners), [p.pid for p in runners]))
1574
                (len(runners), [p.pid for p in runners]))
1567 1575

  
1568 1576
    multi.debug("Joining %d processes" % len(runners))
1569 1577

  
......
1581 1589

  
1582 1590
    # Patch extra parameters into test names by manipulating method docstrings
1583 1591
    for (mname, m) in \
1584
        inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
1592
            inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
1585 1593
        if hasattr(m, __doc__):
1586
            m.__func__.__doc__ = "[%s] %s" % (imagename, m.__doc__)
1594
            m.__func__.__doc__ = "[%s] %s" % (cls.imagename, m.__doc__)
1587 1595

  
1588 1596
    # Make sure the class can be pickled, by listing it among
1589 1597
    # the attributes of __main__. A PicklingError is raised otherwise.
......
1621 1629

  
1622 1630
    # Show staled servers
1623 1631
    print >>sys.stderr, yellow + \
1624
            "Found these stale servers from previous runs:" + \
1625
            normal
1632
        "Found these stale servers from previous runs:" + \
1633
        normal
1626 1634
    print >>sys.stderr, "    " + \
1627
          "\n    ".join(["%d: %s" % (s["id"], s["name"]) for s in stale])
1635
        "\n    ".join(["%d: %s" % (s["id"], s["name"]) for s in stale])
1628 1636

  
1629 1637
    # Delete staled servers
1630 1638
    if delete_stale:
......
1635 1643
        # Wait for all servers to be deleted
1636 1644
        while True:
1637 1645
            servers = c.list_servers()
1638
            stale = [s for s in servers if s["name"].startswith(SNF_TEST_PREFIX)]
1639
            if len(stale)==0:
1646
            stale = [s for s in servers
1647
                     if s["name"].startswith(SNF_TEST_PREFIX)]
1648
            if len(stale) == 0:
1640 1649
                print >> sys.stderr, green + "    ...done" + normal
1641 1650
                break
1642 1651
            elif time.time() > fail_tmout:
1643 1652
                print >> sys.stderr, red + \
1644
                        "Not all stale servers deleted. Action timed out." + \
1645
                        normal
1646
                return
1653
                    "Not all stale servers deleted. Action timed out." + \
1654
                    normal
1655
                sys.exit(1)
1647 1656
            else:
1648 1657
                time.sleep(query_interval)
1649 1658
    else:
......
1662 1671

  
1663 1672
    # Show staled networks
1664 1673
    print >> sys.stderr, yellow + \
1665
            "Found these stale networks from previous runs:" + \
1666
            normal
1674
        "Found these stale networks from previous runs:" + \
1675
        normal
1667 1676
    print "    " + \
1668
          "\n    ".join(["%s: %s" % (str(n["id"]), n["name"]) for n in stale])
1677
        "\n    ".join(["%s: %s" % (str(n["id"]), n["name"]) for n in stale])
1669 1678

  
1670 1679
    # Delete staled networks
1671 1680
    if delete_stale:
......
1676 1685
        # Wait for all networks to be deleted
1677 1686
        while True:
1678 1687
            networks = c.list_networks()
1679
            stale = [n for n in networks if n["name"].startswith(SNF_TEST_PREFIX)]
1680
            if len(stale)==0:
1688
            stale = [n for n in networks
1689
                     if n["name"].startswith(SNF_TEST_PREFIX)]
1690
            if len(stale) == 0:
1681 1691
                print >> sys.stderr, green + "    ...done" + normal
1682 1692
                break
1683 1693
            elif time.time() > fail_tmout:
1684 1694
                print >> sys.stderr, red + \
1685
                        "Not all stale networks deleted. Action timed out." + \
1686
                        normal
1687
                return 
1695
                    "Not all stale networks deleted. Action timed out." + \
1696
                    normal
1697
                sys.exit(1)
1688 1698
            else:
1689 1699
                time.sleep(query_interval)
1690 1700
    else:
......
1695 1705
# Parse arguments functions
1696 1706
def parse_comma(option, opt, value, parser):
1697 1707
    tests = set(['all', 'auth', 'images', 'flavors',
1698
               'servers', 'server_spawn', 'network_spawn'])
1708
                 'servers', 'server_spawn', 'network_spawn'])
1699 1709
    parse_input = value.split(',')
1700 1710

  
1701 1711
    if not (set(parse_input)).issubset(tests):
......
1732 1742
                      help="The token to use for authentication to the API")
1733 1743
    parser.add_option("--nofailfast",
1734 1744
                      action="store_true", dest="nofailfast",
1735
                      help="Do not fail immediately if one of the tests " \
1745
                      help="Do not fail immediately if one of the tests "
1736 1746
                           "fails (EXPERIMENTAL)",
1737 1747
                      default=False)
1738 1748
    parser.add_option("--no-ipv6",
......
1742 1752
    parser.add_option("--action-timeout",
1743 1753
                      action="store", type="int", dest="action_timeout",
1744 1754
                      metavar="TIMEOUT",
1745
                      help="Wait SECONDS seconds for a server action to " \
1755
                      help="Wait SECONDS seconds for a server action to "
1746 1756
                           "complete, then the test is considered failed",
1747 1757
                      default=100)
1748 1758
    parser.add_option("--build-warning",
1749 1759
                      action="store", type="int", dest="build_warning",
1750 1760
                      metavar="TIMEOUT",
1751
                      help="Warn if TIMEOUT seconds have passed and a " \
1761
                      help="Warn if TIMEOUT seconds have passed and a "
1752 1762
                           "build operation is still pending",
1753 1763
                      default=600)
1754 1764
    parser.add_option("--build-fail",
1755 1765
                      action="store", type="int", dest="build_fail",
1756 1766
                      metavar="BUILD_TIMEOUT",
1757
                      help="Fail the test if TIMEOUT seconds have passed " \
1767
                      help="Fail the test if TIMEOUT seconds have passed "
1758 1768
                           "and a build operation is still incomplete",
1759 1769
                      default=900)
1760 1770
    parser.add_option("--query-interval",
1761 1771
                      action="store", type="int", dest="query_interval",
1762 1772
                      metavar="INTERVAL",
1763
                      help="Query server status when requests are pending " \
1773
                      help="Query server status when requests are pending "
1764 1774
                           "every INTERVAL seconds",
1765 1775
                      default=3)
1766 1776
    parser.add_option("--fanout",
1767 1777
                      action="store", type="int", dest="fanout",
1768 1778
                      metavar="COUNT",
1769
                      help="Spawn up to COUNT child processes to execute " \
1770
                           "in parallel, essentially have up to COUNT " \
1779
                      help="Spawn up to COUNT child processes to execute "
1780
                           "in parallel, essentially have up to COUNT "
1771 1781
                           "server build requests outstanding (EXPERIMENTAL)",
1772 1782
                      default=1)
1773 1783
    parser.add_option("--force-flavor",
1774 1784
                      action="store", type="int", dest="force_flavorid",
1775 1785
                      metavar="FLAVOR ID",
1776
                      help="Force all server creations to use the specified "\
1777
                           "FLAVOR ID instead of a randomly chosen one, " \
1786
                      help="Force all server creations to use the specified "
1787
                           "FLAVOR ID instead of a randomly chosen one, "
1778 1788
                           "useful if disk space is scarce",
1779 1789
                      default=None)
1780 1790
    parser.add_option("--image-id",
1781 1791
                      action="store", type="string", dest="force_imageid",
1782 1792
                      metavar="IMAGE ID",
1783
                      help="Test the specified image id, use 'all' to test " \
1793
                      help="Test the specified image id, use 'all' to test "
1784 1794
                           "all available images (mandatory argument)",
1785 1795
                      default=None)
1786 1796
    parser.add_option("--show-stale",
1787 1797
                      action="store_true", dest="show_stale",
1788
                      help="Show stale servers from previous runs, whose "\
1798
                      help="Show stale servers from previous runs, whose "
1789 1799
                           "name starts with `%s'" % SNF_TEST_PREFIX,
1790 1800
                      default=False)
1791 1801
    parser.add_option("--delete-stale",
1792 1802
                      action="store_true", dest="delete_stale",
1793
                      help="Delete stale servers from previous runs, whose "\
1803
                      help="Delete stale servers from previous runs, whose "
1794 1804
                           "name starts with `%s'" % SNF_TEST_PREFIX,
1795 1805
                      default=False)
1796 1806
    parser.add_option("--force-personality",
......
1805 1815
                      default="/var/log/burnin/")
1806 1816
    parser.add_option("--verbose", "-V",
1807 1817
                      action="store_true", dest="verbose",
1808
                      help="Print detailed output about multiple "\
1818
                      help="Print detailed output about multiple "
1809 1819
                           "processes spawning",
1810 1820
                      default=False)
1811 1821
    parser.add_option("--set-tests",
......
1833 1843
    if not opts.show_stale:
1834 1844
        if not opts.force_imageid:
1835 1845
            print >>sys.stderr, red + \
1836
                    "The --image-id argument is mandatory.\n" + \
1837
                    normal
1846
                "The --image-id argument is mandatory.\n" + \
1847
                normal
1838 1848
            parser.print_help()
1839 1849
            sys.exit(1)
1840 1850
        if opts.force_imageid != 'all':
......
1842 1852
                opts.force_imageid = str(opts.force_imageid)
1843 1853
            except ValueError:
1844 1854
                print >>sys.stderr, red + \
1845
                        "Invalid value specified for" + \
1846
                        "--image-id. Use a valid id, or `all'." + \
1847
                        normal
1855
                    "Invalid value specified for" + \
1856
                    "--image-id. Use a valid id, or `all'." + \
1857
                    normal
1848 1858
                sys.exit(1)
1849 1859

  
1850 1860
    # `token' is mandatory
1851 1861
    if not opts.token:
1852 1862
        print >>sys.stderr, red + \
1853
                "The --token argument is mandatory.\n" + \
1854
                normal
1863
            "The --token argument is mandatory.\n" + \
1864
            normal
1855 1865
        parser.print_help()
1856 1866
        sys.exit(1)
1857 1867

  
......
1896 1906

  
1897 1907
    # Initialize a kamaki instance, get flavors, images
1898 1908
    c = ComputeClient(API, TOKEN)
1899

  
1900 1909
    DIMAGES = c.list_images(detail=True)
1901 1910
    DFLAVORS = c.list_flavors(detail=True)
1902 1911

  
......
1904 1913
    # Run them: FIXME: In parallel, FAILEARLY, catchbreak?
1905 1914
    #unittest.main(verbosity=2, catchbreak=True)
1906 1915

  
1916
    # Get a list of images we are going to test
1907 1917
    if opts.force_imageid == 'all':
1908 1918
        test_images = DIMAGES
1909 1919
    else:
1910 1920
        test_images = filter(lambda x: x["id"] == opts.force_imageid, DIMAGES)
1911 1921

  
1912
    #New folder for log per image
1922
    # Create output (logging) folder
1913 1923
    if not os.path.exists(opts.log_folder):
1914 1924
        os.mkdir(opts.log_folder)
1915

  
1916 1925
    test_folder = os.path.join(opts.log_folder, TEST_RUN_ID)
1917 1926
    os.mkdir(test_folder)
1918 1927

  
1919 1928
    for image in test_images:
1920

  
1921 1929
        imageid = str(image["id"])
1922

  
1930
        imagename = image["name"]
1931
        # Choose a flavor (given from user or random)
1923 1932
        if opts.force_flavorid:
1924 1933
            flavorid = opts.force_flavorid
1925 1934
        else:
1926 1935
            flavorid = choice([f["id"] for f in DFLAVORS if f["disk"] >= 20])
1927

  
1928
        imagename = image["name"]
1929

  
1930
        #Personality dictionary for file injection test
1931
        if opts.personality_path != None:
1936
        # Personality dictionary for file injection test
1937
        if opts.personality_path is not None:
1932 1938
            f = open(opts.personality_path)
1933 1939
            content = b64encode(f.read())
1934 1940
            personality = []
1935 1941
            st = os.stat(opts.personality_path)
1936 1942
            personality.append({
1937
                    'path': '/root/test_inj_file',
1938
                    'owner': 'root',
1939
                    'group': 'root',
1940
                    'mode': 0x7777 & st.st_mode,
1941
                    'contents': content
1942
                    })
1943
                'path': '/root/test_inj_file',
1944
                'owner': 'root',
1945
                'group': 'root',
1946
                'mode': 0x7777 & st.st_mode,
1947
                'contents': content})
1943 1948
        else:
1944 1949
            personality = None
1945

  
1950
        # Give a name to our test servers
1946 1951
        servername = "%s%s for %s" % (SNF_TEST_PREFIX, TEST_RUN_ID, imagename)
1947 1952
        is_windows = imagename.lower().find("windows") >= 0
1948 1953

  
1954
        # Create Server TestCases
1949 1955
        ServerTestCase = _spawn_server_test_case(
1950 1956
            imageid=imageid,
1951 1957
            flavorid=flavorid,
......
1956 1962
            action_timeout=opts.action_timeout,
1957 1963
            build_warning=opts.build_warning,
1958 1964
            build_fail=opts.build_fail,
1959
            query_interval=opts.query_interval,
1960
            )
1961

  
1962

  
1965
            query_interval=opts.query_interval)
1966
        # Create Network TestCases
1963 1967
        NetworkTestCase = _spawn_network_test_case(
1964 1968
            action_timeout=opts.action_timeout,
1965 1969
            imageid=imageid,
1966 1970
            flavorid=flavorid,
1967 1971
            imagename=imagename,
1968
            query_interval=opts.query_interval,
1969
            )
1972
            query_interval=opts.query_interval)
1970 1973

  
1974
        # Choose the tests we are going to run
1971 1975
        test_dict = {'auth': UnauthorizedTestCase,
1972 1976
                     'images': ImagesTestCase,
1973 1977
                     'flavors': FlavorsTestCase,
1974 1978
                     'servers': ServersTestCase,
1975 1979
                     'server_spawn': ServerTestCase,
1976 1980
                     'network_spawn': NetworkTestCase}
1977

  
1978 1981
        seq_cases = []
1979 1982
        if 'all' in opts.tests:
1980 1983
            seq_cases = [UnauthorizedTestCase, ImagesTestCase, FlavorsTestCase,
......
1983 1986
            for test in opts.tests:
1984 1987
                seq_cases.append(test_dict[test])
1985 1988

  
1986
        #folder for each image
1989
        # Folder for each image
1987 1990
        image_folder = os.path.join(test_folder, imageid)
1988 1991
        os.mkdir(image_folder)
1989 1992

  
1990
        if opts.fanout>1:
1993
        # Run each test
1994
        if opts.fanout > 1:
1991 1995
            _run_cases_in_parallel(seq_cases, opts.fanout, image_folder)
1992 1996
        else:
1993
            _run_cases_in_series(seq_cases,image_folder)
1997
            _run_cases_in_series(seq_cases, image_folder)
1998

  
1994 1999

  
2000
# --------------------------------------------------------------------
2001
# Call main
1995 2002
if __name__ == "__main__":
1996 2003
    sys.exit(main())

Also available in: Unified diff