Revision 6f8b2632

b/ci/new_config
32 32
kamaki_cloud =
33 33
# Server name to use for our machine
34 34
server_name = Synnefo Deployment
35
# Flavor name (reg expression) to use
36
# This is a list of flavor_names (comma seperated) to try
37
flavor_name = C8R8...D100drbd
38
# Image to use (name must contain this)
39
image_name = OldStable
35
# A list of flavors (comma seperated) to choose from
36
# The user can specify a flavor name (reg expression)
37
# with "name:" or a flavor id with "id:".
38
flavors = name:C8R8...D100drbd, id:1
39
# A list of images (comma seperated) to choose from
40
# The user can specify an image name (reg expression)
41
# with "name:" or an image id with "id:".
42
images = name:Debian Base \(OldStable\), id:72d9844f-1024-4a07-a3c3-60d650b8f5cd
40 43
# File containing the ssh keys to upload/install to server
41 44
# If not set, no ssh keys will be installed
42 45
ssh_keys =
b/ci/snf-ci
55 55
    parser.add_option("--cloud", dest="kamaki_cloud", default=None,
56 56
                      help="Use specified cloud, as is in .kamakirc")
57 57
    parser.add_option("-f", "--flavor", dest="flavor", default=None,
58
                      help="Name of flavor to use for the server.")
58
                      help="Flavor to use for the server."
59
                           " Supports both search by name (reg expression)"
60
                           " with \"name:flavor name\" or by id with"
61
                           " \"id:flavor id\".")
59 62
    parser.add_option("-i", "--image", dest="image", default=None,
60
                      help="UUID of image to use for the server.")
63
                      help="Image to use for the server."
64
                           " Supports both search by name (reg expression)"
65
                           " with \"name:image name\" or by id with"
66
                           " \"id:image id\".")
61 67
    parser.add_option("--ssh-keys", dest="ssh_keys", default=None,
62 68
                      help="Upload/Install the public ssh keys contained"
63 69
                           " in this file to the server")
......
112 118
                           cloud=options.kamaki_cloud)
113 119

  
114 120
    if getattr(options, CREATE_SERVER_CMD, False):
115
        synnefo_ci.create_server(flavor_name=options.flavor,
116
                                 image_id=options.image,
121
        synnefo_ci.create_server(flavor=options.flavor,
122
                                 image=options.image,
117 123
                                 ssh_keys=options.ssh_keys)
118 124
        synnefo_ci.clone_repo(local_repo=options.local_repo)
119 125
    if getattr(options, BUILD_SYNNEFO_CMD, False):
b/ci/utils.py
242 242
            self._wait_transition(server_id, "ACTIVE", "DELETED")
243 243

  
244 244
    @_check_kamaki
245
    def create_server(self, image_id=None, flavor_name=None, ssh_keys=None):
245
    def create_server(self, image=None, flavor=None, ssh_keys=None):
246 246
        """Create slave server"""
247 247
        self.logger.info("Create a new server..")
248 248

  
......
260 260
                          % _green(self.build_id))
261 261

  
262 262
        # Find an image to use
263
        if image_id is None:
264
            image = self._find_image()
265
            self.logger.debug("Will use image \"%s\"" % _green(image['name']))
266
            image_id = image["id"]
267
        self.logger.debug("Image has id %s" % _green(image_id))
263
        image_id = self._find_image(image)
268 264
        # Find a flavor to use
269
        flavor_id = self._find_flavor(flavor_name)
265
        flavor_id = self._find_flavor(flavor)
266

  
267
        # Create Server
270 268
        server = self.cyclades_client.create_server(
271 269
            self.config.get('Deployment', 'server_name'),
272 270
            flavor_id,
......
317 315
        """.format(self.config.get('Global', 'apt_repo'))
318 316
        _run(cmd, False)
319 317

  
320
    def _find_flavor(self, flavor_name):
321
        """Given a flavor_name (reg expression) find a flavor id to use"""
322
        # Get a list of flavor names from config file
323
        flavor_names = self.config.get('Deployment', 'flavor_name').split(",")
324
        if flavor_name is not None:
318
    def _find_flavor(self, flavor=None):
319
        """Find a suitable flavor to use
320

  
321
        Search by name (reg expression) or by id
322
        """
323
        # Get a list of flavors from config file
324
        flavors = self.config.get('Deployment', 'flavors').split(",")
325
        if flavor is not None:
325 326
            # If we have a flavor_name to use, add it to our list
326
            flavor_names.insert(0, flavor_name)
327

  
328
        flavors = self.compute_client.list_flavors()
329
        for flname in flavor_names:
330
            sflname = flname.strip()
331
            self.logger.debug("Try to find a flavor with name \"%s\"" % sflname)
332
            fls = [f for f in flavors
333
                   if re.search(sflname, f['name']) is not None]
334
            if fls:
335
                self.logger.debug("Will use %s with id %s"
336
                                  % (fls[0]['name'], fls[0]['id']))
337
                return fls[0]['id']
327
            flavors.insert(0, flavor)
328

  
329
        list_flavors = self.compute_client.list_flavors()
330
        for flv in flavors:
331
            [flv_type, flv_value] = flv.strip().split(':')
332
            if flv_type == "name":
333
                # Filter flavors by name
334
                self.logger.debug(
335
                    "Trying to find a flavor with name \"%s\"" % flv_value)
336
                list_flvs = \
337
                    [f for f in list_flavors
338
                     if re.search(flv_value, f['name'], flags=re.I) is not None]
339
            elif flv_type == "id":
340
                # Filter flavors by id
341
                self.logger.debug(
342
                    "Trying to find a flavor with id \"%s\"" % flv_value)
343
                list_flvs = \
344
                    [f for f in list_flavors
345
                     if f['id'].lower() == flv_value.lower()]
346
            else:
347
                self.logger.error("Unrecognized flavor type %s" % flv_type)
348

  
349
            # Check if we found one
350
            if list_flvs:
351
                self.logger.debug("Will use \"%s\" with id \"%s\""
352
                                  % (list_flvs[0]['name'], list_flvs[0]['id']))
353
                return list_flvs[0]['id']
338 354

  
339 355
        self.logger.error("No matching flavor found.. aborting")
340 356
        sys.exit(1)
341 357

  
342
    def _find_image(self):
358
    def _find_image(self, image=None):
343 359
        """Find a suitable image to use
344 360

  
345
        It has to belong to one of the `DEFAULT_SYSTEM_IMAGES_UUID'
346
        users and contain the word given by `image_name' option.
361
        In case of search by name, the image has to belong to one
362
        of the `DEFAULT_SYSTEM_IMAGES_UUID' users.
363
        In case of search by id it only has to exist.
347 364
        """
348
        image_name = self.config.get('Deployment', 'image_name').lower()
349
        images = self.image_client.list_public(detail=True)['images']
350
        # Select images by `system_uuid' user
351
        images = [x for x in images
352
                  if x['user_id'] in DEFAULT_SYSTEM_IMAGES_UUID]
353
        # Select images with `image_name' in their names
354
        images = [x for x in images
355
                  if x['name'].lower().find(image_name) != -1]
356
        # Let's select the first one
357
        return images[0]
365
        # Get a list of images from config file
366
        images = self.config.get('Deployment', 'images').split(",")
367
        if image is not None:
368
            # If we have an image from command line, add it to our list
369
            images.insert(0, image)
370

  
371
        list_images = self.image_client.list_public(detail=True)['images']
372
        for img in images:
373
            [img_type, img_value] = img.strip().split(':')
374
            if img_type == "name":
375
                # Filter images by name
376
                self.logger.debug(
377
                    "Trying to find an image with name \"%s\"" % img_value)
378
                list_imgs = \
379
                    [i for i in list_images
380
                     if i['user_id'] in DEFAULT_SYSTEM_IMAGES_UUID and
381
                        re.search(img_value, i['name'], flags=re.I) is not None]
382
            elif img_type == "id":
383
                # Filter images by id
384
                self.logger.debug(
385
                    "Trying to find an image with id \"%s\"" % img_value)
386
                list_imgs = \
387
                    [i for i in list_images
388
                     if i['id'].lower() == img_value.lower()]
389
            else:
390
                self.logger.error("Unrecognized image type %s" % img_type)
391
                sys.exit(1)
392

  
393
            # Check if we found one
394
            if list_imgs:
395
                self.logger.debug("Will use \"%s\" with id \"%s\""
396
                                  % (list_imgs[0]['name'], list_imgs[0]['id']))
397
                return list_imgs[0]['id']
398

  
399
        # We didn't found one
400
        self.logger.error("No matching image found.. aborting")
401
        sys.exit(1)
358 402

  
359 403
    def _get_server_ip_and_port(self, server):
360 404
        """Compute server's IPv4 and ssh port number"""
......
614 658
        self.logger.info("Deploy Synnefo..")
615 659
        if schema is None:
616 660
            schema = self.config.get('Global', 'schema')
617
        self.logger.debug("Will use %s schema" % schema)
661
        self.logger.debug("Will use \"%s\" schema" % schema)
618 662

  
619 663
        schema_dir = os.path.join(self.ci_dir, "schemas/%s" % schema)
620 664
        if not (os.path.exists(schema_dir) and os.path.isdir(schema_dir)):

Also available in: Unified diff