Revision c2f037ff snf-tools/synnefo_tools/burnin/cyclades_common.py

b/snf-tools/synnefo_tools/burnin/cyclades_common.py
49 49

  
50 50
from kamaki.clients import ClientError
51 51

  
52
from synnefo_tools.burnin.common import BurninTests, MB, GB
52
from synnefo_tools.burnin.common import BurninTests, MB, GB, QADD, QREMOVE, \
53
    QDISK, QVM, QRAM, QIP, QCPU, QNET
53 54

  
54 55

  
55 56
# pylint: disable=too-many-public-methods
56 57
class CycladesTests(BurninTests):
57 58
    """Extends the BurninTests class for Cyclades"""
59
    def _parse_images(self):
60
        """Find images given to command line"""
61
        if self.images is None:
62
            self.info("No --images given. Will use the default %s",
63
                      "^Debian Base$")
64
            filters = ["name:^Debian Base$"]
65
        else:
66
            filters = self.images
67
        avail_images = self._find_images(filters)
68
        self.info("Found %s images to choose from", len(avail_images))
69
        return avail_images
70

  
71
    def _parse_flavors(self):
72
        """Find flavors given to command line"""
73
        flavors = self._get_list_of_flavors(detail=True)
74

  
75
        if self.flavors is None:
76
            self.info("No --flavors given. Will use all of them")
77
            avail_flavors = flavors
78
        else:
79
            avail_flavors = self._find_flavors(self.flavors, flavors=flavors)
80

  
81
        self.info("Found %s flavors to choose from", len(avail_flavors))
82
        return avail_flavors
83

  
58 84
    def _try_until_timeout_expires(self, opmsg, check_fun):
59 85
        """Try to perform an action until timeout expires"""
60 86
        assert callable(check_fun), "Not a function"
......
113 139
                      server['name'], server['id'])
114 140
        return self.clients.cyclades.get_server_details(server['id'])
115 141

  
116
    def _create_server(self, image, flavor, personality=None, network=False):
142
    # pylint: disable=too-many-arguments
143
    def _create_server(self, image, flavor, personality=None,
144
                       network=False, project_id=None):
117 145
        """Create a new server"""
118 146
        if network:
119
            fip = self._create_floating_ip()
147
            fip = self._create_floating_ip(project_id=project_id)
120 148
            port = self._create_port(fip['floating_network_id'],
121 149
                                     floating_ip=fip)
122 150
            networks = [{'port': port['id']}]
......
129 157
        self.info("Using flavor %s with id %s", flavor['name'], flavor['id'])
130 158
        server = self.clients.cyclades.create_server(
131 159
            servername, flavor['id'], image['id'],
132
            personality=personality, networks=networks)
160
            personality=personality, networks=networks,
161
            project=project_id)
133 162

  
134 163
        self.info("Server id: %s", server['id'])
135 164
        self.info("Server password: %s", server['adminPass'])
......
138 167
        self.assertEqual(server['flavor']['id'], flavor['id'])
139 168
        self.assertEqual(server['image']['id'], image['id'])
140 169
        self.assertEqual(server['status'], "BUILD")
170
        if project_id is None:
171
            project_id = self._get_uuid()
172
        self.assertEqual(server['tenant_id'], project_id)
141 173

  
142 174
        # Verify quotas
143
        self._check_quotas(disk=+int(flavor['disk'])*GB,
144
                           vm=+1,
145
                           ram=+int(flavor['ram'])*MB,
146
                           cpu=+int(flavor['vcpus']))
175
        changes = \
176
            {project_id:
177
                [(QDISK, QADD, flavor['disk'], GB),
178
                 (QVM, QADD, 1, None),
179
                 (QRAM, QADD, flavor['ram'], MB),
180
                 (QCPU, QADD, flavor['vcpus'], None)]}
181
        self._check_quotas(changes)
147 182

  
148 183
        return server
149 184

  
......
180 215
            self.assertNotIn(srv['id'], new_servers)
181 216

  
182 217
        # Verify quotas
183
        flavors = \
184
            [self.clients.compute.get_flavor_details(srv['flavor']['id'])
185
             for srv in servers]
186
        self._verify_quotas_deleted(flavors)
218
        self._verify_quotas_deleted(servers)
187 219

  
188
    def _verify_quotas_deleted(self, flavors):
220
    def _verify_quotas_deleted(self, servers):
189 221
        """Verify quotas for a number of deleted servers"""
190
        used_disk = 0
191
        used_vm = 0
192
        used_ram = 0
193
        used_cpu = 0
194
        for flavor in flavors:
195
            used_disk += int(flavor['disk']) * GB
196
            used_vm += 1
197
            used_ram += int(flavor['ram']) * MB
198
            used_cpu += int(flavor['vcpus'])
199
        self._check_quotas(disk=-used_disk,
200
                           vm=-used_vm,
201
                           ram=-used_ram,
202
                           cpu=-used_cpu)
222
        changes = dict()
223
        for server in servers:
224
            project = server['tenant_id']
225
            if project not in changes:
226
                changes[project] = []
227
            flavor = \
228
                self.clients.compute.get_flavor_details(server['flavor']['id'])
229
            new_changes = [
230
                (QDISK, QREMOVE, flavor['disk'], GB),
231
                (QVM, QREMOVE, 1, None),
232
                (QRAM, QREMOVE, flavor['ram'], MB),
233
                (QCPU, QREMOVE, flavor['vcpus'], None)]
234
            changes[project].extend(new_changes)
235

  
236
        self._check_quotas(changes)
203 237

  
204 238
    def _get_connection_username(self, server):
205 239
        """Determine the username to use to connect to the server"""
......
320 354
                           "Can not get IPs from server attachments")
321 355

  
322 356
        for addr in addrs:
323
            self.assertEquals(IPy.IP(addr).version(), version)
357
            self.assertEqual(IPy.IP(addr).version(), version)
324 358

  
325 359
        if network is None:
326 360
            msg = "Server's public IPv%s is %s"
......
411 445

  
412 446
    # ----------------------------------
413 447
    # Networks
414
    def _create_network(self, cidr="10.0.1.0/28", dhcp=True):
448
    def _create_network(self, cidr="10.0.1.0/28", dhcp=True,
449
                        project_id=None):
415 450
        """Create a new private network"""
416 451
        name = self.run_id
417 452
        network = self.clients.network.create_network(
418
            "MAC_FILTERED", name=name, shared=False)
453
            "MAC_FILTERED", name=name, shared=False,
454
            project=project_id)
419 455
        self.info("Network with id %s created", network['id'])
420 456
        subnet = self.clients.network.create_subnet(
421 457
            network['id'], cidr=cidr, enable_dhcp=dhcp)
422 458
        self.info("Subnet with id %s created", subnet['id'])
423 459

  
424 460
        # Verify quotas
425
        self._check_quotas(network=+1)
461
        if project_id is None:
462
            project_id = self._get_uuid()
463
        changes = \
464
            {project_id: [(QNET, QADD, 1, None)]}
465
        self._check_quotas(changes)
426 466

  
427 467
        #Test if the right name is assigned
428 468
        self.assertEqual(network['name'], name)
469
        self.assertEqual(network['tenant_id'], project_id)
429 470

  
430 471
        return network
431 472

  
......
450 491
            self.assertNotIn(net['id'], new_networks)
451 492

  
452 493
        # Verify quotas
453
        self._check_quotas(network=-len(networks))
494
        changes = \
495
            {self._get_uuid(): [(QNET, QREMOVE, len(networks), None)]}
496
        self._check_quotas(changes)
454 497

  
455 498
    def _get_public_network(self, networks=None):
456 499
        """Get the public network"""
......
462 505
                return net
463 506
        self.fail("Could not find a public network to use")
464 507

  
465
    def _create_floating_ip(self):
508
    def _create_floating_ip(self, project_id=None):
466 509
        """Create a new floating ip"""
467 510
        pub_net = self._get_public_network()
468 511
        self.info("Creating a new floating ip for network with id %s",
469 512
                  pub_net['id'])
470
        fip = self.clients.network.create_floatingip(pub_net['id'])
513
        fip = self.clients.network.create_floatingip(
514
            pub_net['id'], project=project_id)
471 515
        # Verify that floating ip has been created
472 516
        fips = self.clients.network.list_floatingips()
473 517
        fips = [f['id'] for f in fips]
474 518
        self.assertIn(fip['id'], fips)
475 519
        # Verify quotas
476
        self._check_quotas(ip=+1)
520
        if project_id is None:
521
            project_id = self._get_uuid()
522
        changes = \
523
            {project_id: [(QIP, QADD, 1, None)]}
524
        self._check_quotas(changes)
525

  
477 526
        # Check that IP is IPv4
478
        self.assertEquals(IPy.IP(fip['floating_ip_address']).version(), 4)
527
        self.assertEqual(IPy.IP(fip['floating_ip_address']).version(), 4)
528
        self.assertEqual(fip['tenant_id'], project_id)
479 529

  
480 530
        self.info("Floating IP %s with id %s created",
481 531
                  fip['floating_ip_address'], fip['id'])
......
588 638
        list_ips = [f['id'] for f in self.clients.network.list_floatingips()]
589 639
        for fip in fips:
590 640
            self.assertNotIn(fip['id'], list_ips)
641

  
591 642
        # Verify quotas
592
        self._check_quotas(ip=-len(fips))
643
        changes = dict()
644
        for fip in fips:
645
            project = fip['tenant_id']
646
            if project not in changes:
647
                changes[project] = []
648
            changes[project].append((QIP, QREMOVE, 1, None))
649
        self._check_quotas(changes)
650

  
651
    def _find_project(self, flavors, projects=None):
652
        """Return a pair of flavor, project that we can use"""
653
        if projects is None:
654
            projects = self.quotas.keys()
655

  
656
        # XXX: Well there seems to be no easy way to find how many resources
657
        # we have left in a project (we have to substract usage from limit,
658
        # check both per_user and project quotas, blah, blah). For now
659
        # just return the first flavor with the first project and lets hope
660
        # that it fits.
661
        return (flavors[0], projects[0])
662

  
663
        # # Get only the quotas for the given 'projects'
664
        # quotas = dict()
665
        # for prj, qts in self.quotas.items():
666
        #     if prj in projects:
667
        #         quotas[prj] = qts
668
        #
669
        # results = []
670
        # for flv in flavors:
671
        #     for prj, qts in quotas.items():
672
        #         self.debug("Testing flavor %s, project %s", flv['name'], prj)
673
        #         condition = \
674
        #             (flv['ram'] <= qts['cyclades.ram']['usage'] and
675
        #              flv['vcpus'] <= qts['cyclades.cpu']['usage'] and
676
        #              flv['disk'] <= qts['cyclades.disk']['usage'] and
677
        #              qts['cyclades.vm']['usage'] >= 1)
678
        #         if condition:
679
        #             results.append((flv, prj))
680
        #
681
        # if not results:
682
        #     msg = "Couldn't find a suitable flavor to use for current qutoas"
683
        #     self.error(msg)
684
        #
685
        # return random.choice(results)
593 686

  
594 687

  
595 688
class Retry(Exception):

Also available in: Unified diff