Ejemplo n.º 1
0
def create(caller_id, name, description, filesystem, size, disk_controller):
    """
    Method creates new Image. It's only used by disk_volume type (only url view with create)
    @cmview_user

    @parameter{name,string}
    @parameter{description,string}
    @parameter{filesystem,int} id of the filesystem. Supported filesystems are listed in settings
    @parameter{size,int} size of the Image to create [MB]
    @parameter{disk_controller}

    @response{dict} Image's dictionary
    """
    if size < 1:
        raise CMException('image_invalid_size')

    user = User.get(caller_id)
    user.check_storage(size)
    image = StorageImage.create(user=user, disk_controller=disk_controller, description=description, name=name,
                                size=size)

    try:
        image.save()
    except Exception, e:
        log.error(caller_id, "Unable to save image to DB: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 2
0
def attach(caller_id, storage_image_id, vm_id):
    # vm_id, img_id, destination='usb', check=True/False
    """
    Attaches selected storage disk to specified Virtual Machine. Such disk may be
    mounted to VM so that data generated by VM may be stored on it. VM also gains
    access to data already stored on that storage disk.

    @cmview_user

    @parameter{storage_image_id,int} id of block device (should be Storage type) - Disk Volume Image
    @parameter{vm_id,int} id of the VM which Storage Image should be attached to

    @response{None}
    """
    vm = VM.get(caller_id, vm_id)
    disk = StorageImage.get(caller_id, storage_image_id)

    # Check if disk is already attached to a vm
    if disk.vm:
        raise CMException('image_attached')

    disk.attach(vm)

    try:
        disk.save()
    except:
        raise CMException('storage_image_attach')
Ejemplo n.º 3
0
def download(caller_id, description, name, path, disk_dev, disk_controller):
    """
    Downloads image depending on the \c data parameter.
    @cmview_admin_cm

    @parameter{description,string}
    @parameter{name,string}
    @parameter{path,string} HTTP or FTP path to image to download
    @parameter{type,image_types} type of image, automatically set, type is in the URL requested

    @response{None}
    """

    # size value is taken
    try:
        connection = urllib.urlopen(path)
        size = int(connection.info()["Content-Length"])
    except IOError:
        log.exception('Cannot find image')
        raise CMException('image_not_found')
    except KeyError:
        log.exception(caller_id, 'Cannot calculate size')
        raise CMException('image_calculate_size')

    user = User.get(caller_id)

    image = StorageImage.create(name=name, description=description, user=user, disk_dev=disk_dev,  disk_controller=disk_controller)

    try:
        image.save()
    except Exception, e:
        log.error(caller_id, "Unable to save image to DB: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 4
0
def download(caller_id, description, name, path, disk_dev, disk_controller):
    """
    Downloads specified StorateImage from remote path.

    @cmview_admin_cm
    @param_post{description,string}
    @param_post{name,string} how to name newly downloaded storage image
    @param_post{path,string} HTTP or FTP path to download StorageImage.
    @param_post{disk_dev}
    @param_post{disk_controller}
    """

    # size value is taken
    try:
        connection = urllib.urlopen(path)
        size = int(connection.info()["Content-Length"])
    except IOError:
        log.exception('Cannot find image')
        raise CMException('image_not_found')
    except KeyError:
        log.exception(caller_id, 'Cannot calculate size')
        raise CMException('image_calculate_size')

    user = User.get(caller_id)

    image = StorageImage.create(name=name, description=description, user=user, disk_dev=disk_dev,  disk_controller=disk_controller)

    try:
        image.save()
    except Exception, e:
        log.error(caller_id, "Unable to save image to DB: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 5
0
def edit(caller_id, storage_image_id, name, description, disk_controller):
    """
    Sets Image's new attributes. Those should be get by src.cm.manager.image.get_by_id().
    @cmview_admin_cm

    @parameter{system_image_id,string} new Image name
    @parameter{name,string} new Image name
    @parameter{description,string} new Image description
    @parameter{disk_controller} new Image controller optional
    @parameter{video_device} new video device optional
    @parameter{network_device} new network device optional
    @parameter{platform} optional
    """

    image = StorageImage.admin_get(storage_image_id)

    if image.state != image_states['ok']:
        raise CMException('image_edit')

    image.name = name
    image.description = description
    image.disk_controller = disk_controller

    try:
        image.save()
    except:
        raise CMException('image_edit')
Ejemplo n.º 6
0
def create(caller_id, name, description, filesystem, size, disk_controller):
    """
    Creates new StorageImage.

    @cmview_user
    @param_post{name,string}
    @param_post{description,string}
    @param_post{filesystem,int} id of the filesystem. Supported filesystems are
    common.hardware.disk_filesystems
    @param_post{size,int} size of the SystemImage to create [MB]
    @param_post{disk_controller}

    @response{dict} StorageImage.dict property of newly created StorageImage
    """
    if size < 1:
        raise CMException('image_invalid_size')

    user = User.get(caller_id)
    user.check_storage(size)
    image = StorageImage.create(user=user, disk_controller=disk_controller, description=description, name=name,
                                size=size)

    try:
        image.save()
    except Exception, e:
        log.error(caller_id, "Unable to save image to DB: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 7
0
def get_by_id(caller_id, storage_image_id):
    """
    @cmview_user
    @param_post{storage_image_id,int} id of the requested StorageImage

    @response{dict} StorageImage.dict property of the requested StorageImage
    """
    return StorageImage.get(caller_id, storage_image_id).dict
Ejemplo n.º 8
0
def get_by_id(caller_id, storage_image_id):
    """
    @cmview_user

    @parameter{storage_image_id,int} id of the Image to get

    @response{dict} extended information about specified Image
    """
    return StorageImage.get(caller_id, storage_image_id).dict
Ejemplo n.º 9
0
def copy(caller_id, src_image_id, dest_user_id):
    """
    Copy selected StorageImage to user's StorageImages

    @cmview_admin_cm
    @param_post{src_image_id,int}
    @param_post{dest_user_id,int}
    """
    src_image = StorageImage.admin_get(src_image_id)
    dest_user = User.get(dest_user_id)
    dest_image = StorageImage.create(name=src_image.name, description=src_image.description, user=dest_user,
                                    disk_controller=src_image.disk_controller, size=src_image.size)

    try:
        dest_image.save()
    except Exception, e:
        log.error(caller_id, "Unable to commit: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 10
0
def get_by_id(caller_id, storage_image_id):
    """
    Fetch requested StorageImage.

    @cmview_admin_cm
    @param_post{storage_image_id,int} id of the requested StorageImage

    @response{dict} StorageImages.dict property for requested StorageImage
    """
    return StorageImage.admin_get(storage_image_id).dict
Ejemplo n.º 11
0
def get_by_id(caller_id, storage_image_id):
    """
    @cmview_admin_cm

    @parameter{image_id,int} id of the Image to get
    @parameter{type,image_types} type of image, automatically set, type is in the URL requested

    @response{dict} extended information about specified Image
    """
    return StorageImage.admin_get(storage_image_id).dict
Ejemplo n.º 12
0
def delete(caller_id, storage_image_id):
    """
    Deletes given Image
    @cmview_admin_cm

    @parameter{system_image_id} id of the Image to delete
    @parameter{type,image_types} type of image, automatically set, type is in the URL requested
    """
    image = StorageImage.admin_get(storage_image_id)

    image.check_attached()
    image.state = image_states['locked']
    image.save()
Ejemplo n.º 13
0
def delete(caller_id, storage_image_id):
    """
    Sets StorageImage state as @val{locked}.

    @cmview_admin_cm
    @param_post{storage_image_id} id of the Image to delete

    @todo Should rather delete StorageImage and set its state to 'deleted'.
    """
    image = StorageImage.admin_get(storage_image_id)

    image.check_attached()
    image.state = image_states['locked']
    image.save()
Ejemplo n.º 14
0
def convert_to_system_image(caller_id, storage_image_id, platform, disk_controller, network_device, video_device):
    """
    @cmview_user
    """
    image = StorageImage.get(caller_id, storage_image_id)
    image.platform = platform
    image.disk_controller = disk_controller
    image.network_device = network_device
    image.video_device = video_device

    try:
        image.recast('cm.systemimage')
        image.save()
    except Exception:
        raise CMException('image_change_type')
Ejemplo n.º 15
0
def detach(caller_id, storage_image_id, vm_id):
    """
    Detaches specified StorageImage from specified VM.

    @cmview_user
    @param_post{vm_id,int} id of the VM StorageImage should be detached from
    @param_post{storage_image_id,int} id of the StorageImage to detach
    """
    vm = VM.get(caller_id, vm_id)
    disk = StorageImage.get(caller_id, storage_image_id)

    disk.detach(vm)

    try:
        disk.save()
    except:
        raise CMException('storage_image_attach')
Ejemplo n.º 16
0
def delete(caller_id, storage_image_id):
    """
    Deletes given Image
    @cmview_user

    @parameter{storage_image_id} id of the Image to delete
    """
    image = StorageImage.get(caller_id, storage_image_id)

    if image.state != image_states['ok']:
        raise CMException('image_delete')

    image.check_attached()
    try:
        subprocess.call(['rm', image.path])
    except Exception, e:
        raise CMException('image_delete')
Ejemplo n.º 17
0
def delete(caller_id, storage_image_id):
    """
    Deletes given StorageImage from CM storage space. Such an StorageImage
    can in no way be restored. It's also deleted from database.

    @cmview_user
    @param_post{storage_image_ids,list(int)} id of the StorageImage to delete
    """
    image = StorageImage.get(caller_id, storage_image_id)

    if image.state != image_states['ok']:
        raise CMException('image_delete')

    image.check_attached()
    try:
        subprocess.call(['rm', image.path])
    except Exception, e:
        raise CMException('image_delete')
Ejemplo n.º 18
0
def detach(caller_id, storage_image_id, vm_id):
    """
    Detaches specified storage disk from specified VM.
    @cmview_user

    @parameter{vm_id,int} id of the VM from which to detach Image
    @parameter{storage_image_id,int} id of the Storage Image to detach - Disk Volume Image

    @response{None}
    """
    vm = VM.get(caller_id, vm_id)
    disk = StorageImage.get(caller_id, storage_image_id)

    disk.detach(vm)

    try:
        disk.save()
    except:
        raise CMException('storage_image_attach')
Ejemplo n.º 19
0
def convert_to_system_image(caller_id, storage_image_id):
    """
    Converts specified StorageImage to SystemImage. After convertion it's not
    available as StorageImage anymore. File is moved and StorageImage entry is
    removed from database.

    @cmview_admin_cm
    @param_post{storage_image_id,int} ID of an StorageImage to convert
    """
    image = StorageImage.admin_get(storage_image_id)

    system_image = SystemImage.create(name=image.name, description=image.description, user=image.user, disk_controller=image.disk_controller)
    system_image.state = image_states['ok']
    system_image.size = image.size

    try:
        system_image.save()
        os.rename(image.path, system_image.path)
        image.delete()
    except Exception:
        raise CMException('image_change_type')
Ejemplo n.º 20
0
def convert_to_system_image(caller_id, storage_image_id):
    """
    Changes type of the given Image.
    @cmview_admin_cm

    @parameter{system_image_id,int} ID of an Image to change type of

    @response{None}
    """
    image = StorageImage.admin_get(storage_image_id)

    system_image = SystemImage.create(name=image.name, description=image.description, user=image.user, disk_controller=image.disk_controller)
    system_image.state = image_states['ok']
    system_image.size = image.size

    try:
        system_image.save()
        os.rename(image.path, system_image.path)
        image.delete()
    except Exception:
        raise CMException('image_change_type')
Ejemplo n.º 21
0
def download(caller_id, name, description, path, disk_controller):
    """
    Downloads image depending on the \c data parameter.
    @cmview_user

    @parameter{name,string}
    @parameter{description,string}
    @parameter{path,string} HTTP or FTP path to image to download
    @parameter{disk_controller}

    @response{None}
    """
    user = User.get(caller_id)

    if path.startswith('/'):
        size = os.path.getsize(path.strip())
    else:
        if not any([path.startswith('http://'), path.startswith('https://'), path.startswith('ftp://')]):
            path = 'http://' + path.strip()

        # size value is taken
        try:
            connection = urllib.urlopen(path)
            size = int(connection.info()["Content-Length"])
        except IOError:
            log.exception(caller_id, 'Cannot find image')
            raise CMException('image_not_found')
        except KeyError:
            log.exception(caller_id, 'Cannot calculate size')
            raise CMException('image_calculate_size')

    user.check_storage(size / (1024 * 1024))

    image = StorageImage.create(name=name, description=description, user=user, disk_controller=disk_controller)

    try:
        image.save()
    except Exception, e:
        log.error(caller_id, "Unable to save image to DB: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 22
0
def download(caller_id, name, description, path, disk_controller):
    """
    Downloads specified StorageImage.

    @cmview_user
    @param_post{name,string}
    @param_post{description,string}
    @param_post{path,string} HTTP or FTP path to StorageImage to download
    @param_post{disk_controller}
    """
    user = User.get(caller_id)

    if path.startswith('/'):
        size = os.path.getsize(path.strip())
    else:
        if not any([path.startswith('http://'), path.startswith('https://'), path.startswith('ftp://')]):
            path = 'http://' + path.strip()

        # size value is taken
        try:
            connection = urllib.urlopen(path)
            size = int(connection.info()["Content-Length"])
        except IOError:
            log.exception(caller_id, 'Cannot find image')
            raise CMException('image_not_found')
        except KeyError:
            log.exception(caller_id, 'Cannot calculate size')
            raise CMException('image_calculate_size')

    user.check_storage(size / (1024 * 1024))

    image = StorageImage.create(name=name, description=description, user=user, disk_controller=disk_controller)

    try:
        image.save()
    except Exception, e:
        log.error(caller_id, "Unable to save image to DB: %s" % str(e))
        raise CMException('image_create')
Ejemplo n.º 23
0
def edit(caller_id, storage_image_id, name, description, disk_controller):
    """
    Sets Image's new attributes. Those should be get by src.cm.manager.image.get_by_id().
    @cmview_user

    @parameter{storage_image_id,int} id of the Image to edit
    @parameter{name,string} new Image name
    @parameter{description,string} new Image description
    @parameter{disk_controller} new Image controller optional
    """

    image = StorageImage.get(caller_id, storage_image_id)

    if not image.state in [image_states['ok'], image_states['adding']]:
        raise CMException('image_edit')

    image.name = name
    image.description = description
    image.disk_controller = disk_controller
    try:
        image.save(update_fields=['name', 'description', 'disk_controller'])
    except:
        raise CMException('image_edit')
Ejemplo n.º 24
0
def edit(caller_id, storage_image_id, name, description, disk_controller):
    """
    Sets Image's new attributes. Those should be get by src.cm.manager.image.get_by_id().

    @cmview_user
    @param_post{storage_image_id,int} id of the Image to edit
    @param_post{name,string} new Image name
    @param_post{description,string} new Image description
    @param_post{disk_controller} new Image controller optional
    """

    image = StorageImage.get(caller_id, storage_image_id)

    if not image.state in [image_states['ok'], image_states['adding']]:
        raise CMException('image_edit')

    image.name = name
    image.description = description
    image.disk_controller = disk_controller
    try:
        image.save(update_fields=['name', 'description', 'disk_controller'])
    except:
        raise CMException('image_edit')
Ejemplo n.º 25
0
def convert_to_system_image(caller_id, storage_image_id, platform, disk_controller, network_device, video_device):
    """
    Converts StorageImage to SystemImage so that it may be selected as os
    container when creating new VM.

    @cmview_user
    @param_post{storage_image_id,int}
    @param_post{platform}
    @param_post{disk_controller}
    @param_post{network_device}
    @param_post{video_device}
    """
    image = StorageImage.get(caller_id, storage_image_id)
    image.platform = platform
    image.disk_controller = disk_controller
    image.network_device = network_device
    image.video_device = video_device

    try:
        image.recast('cm.systemimage')
        image.save()
    except Exception:
        raise CMException('image_change_type')
Ejemplo n.º 26
0
def attach(caller_id, storage_image_id, vm_id):
    # vm_id, img_id, destination='usb', check=True/False
    """
    Attaches selected StorageImage to specified VM. Such a disk may be mounted
    to VM so that data generated by VM could be stored on it. VM also has
    access to data already stored on that attached StorageImage.

    @cmview_user
    @param_post{storage_image_id,int} id of a StorageImage block device - Disk Volume Image
    @param_post{vm_id,int} id of the VM which StorageImage should be attached to
    """
    vm = VM.get(caller_id, vm_id)
    disk = StorageImage.get(caller_id, storage_image_id)

    # Check if disk is already attached to a vm
    if disk.vm:
        raise CMException('image_attached')

    disk.attach(vm)

    try:
        disk.save()
    except:
        raise CMException('storage_image_attach')
Ejemplo n.º 27
0
def edit(caller_id, storage_image_id, name, description, disk_controller):
    """
    Updates Image's attributes.

    @cmview_admin_cm
    @param_post{storage_image_id,string}
    @param_post{name,string} new Image name
    @param_post{description,string} new Image description
    @param_post{disk_controller} new Image controller optional
    """

    image = StorageImage.admin_get(storage_image_id)

    if image.state != image_states['ok']:
        raise CMException('image_edit')

    image.name = name
    image.description = description
    image.disk_controller = disk_controller

    try:
        image.save()
    except:
        raise CMException('image_edit')
Ejemplo n.º 28
0
def convert_to_storage_image(caller_id, system_image_id):
    """
    Changes type of the given Image.

    @cmview_admin_cm
    @param_post{system_image_id,int} ID of an Image to change type of

    @response{None}
    """
    image = SystemImage.admin_get(system_image_id)

    storage_image = StorageImage.create(name=image.name,
                                        description=image.description,
                                        user=image.user,
                                        disk_controller=image.disk_controller)
    storage_image.state = image_states['ok']
    storage_image.size = image.size

    try:
        storage_image.save()
        os.rename(image.path, storage_image.path)
        image.delete()
    except Exception:
        raise CMException('image_change_type')
Ejemplo n.º 29
0
    def create(user,
               name,
               description,
               image_id,
               template_id,
               public_ip_id,
               iso_list,
               disk_list,
               vnc,
               groups,
               ssh_key=None,
               ssh_username=None,
               count=1,
               farm=None,
               head_template_id=None,
               node_id=False,
               lease_id=None,
               user_data=None):
        from cm.models.storage_image import StorageImage
        from cm.utils.threads.vm import VMThread

        template = Template.get(template_id)
        image = SystemImage.get(user.id, image_id, groups)

        if image.state != image_states['ok']:
            raise CMException('image_unavailable')

        if farm:
            head_template = Template.get(head_template_id)
            wn_template = template
            user.check_quota([(head_template, 1), (wn_template, count)])
            count += 1
        else:
            user.check_quota([(template, count)])

        vms = []

        reservation_id = None

        for i in range(count):
            # create VM instance
            log.debug(user.id, "Looking for node")
            node = Node.get_free_node(
                head_template, image,
                node_id) if farm and i == 0 else Node.get_free_node(
                    template, image, node_id)
            log.info(user.id, 'Selected node: %d' % node.id)
            vm = VM()
            vm.libvirt_id = -1
            if farm:
                if i == 0:
                    vm.name = '%s-head' % name
                    vm.description = 'Farm head'
                    vm.template = head_template
                else:
                    vm.name = '%s-wn%d' % (name, i)
                    vm.description = 'Worker Node'
                    vm.template = wn_template
            else:
                vm.template = template
                vm.description = description
                if count > 1:
                    vm.name = '%s_%d' % (name, i + 1)
                else:
                    vm.name = name
            vm.user = user
            vm.state = vm_states['init']
            vm.start_time = datetime.now()
            vm.system_image = image
            vm.node = node
            vm.save_vm = True
            if farm:
                vm.farm = farm

            # Find first free vnc port
            used_ports = VM.objects.exclude(
                state__in=[vm_states['closed'], vm_states['erased']
                           ]).values_list('vnc_port', flat=True)

            for new_vnc_port in xrange(VNC_PORTS['START'],
                                       VNC_PORTS['END'] + 1):
                if new_vnc_port not in used_ports and new_vnc_port not in VNC_PORTS[
                        'EXCLUDE']:
                    break
            else:
                raise CMException('vm_vnc_not_found')

            log.debug(user.id, "Found vnc port: %d" % new_vnc_port)
            vm.vnc_port = new_vnc_port

            # Find first free novnc port
            used_ports = VM.objects.exclude(
                state__in=[vm_states['closed'], vm_states['erased']
                           ]).values_list('novnc_port', flat=True)
            for new_novnc_port in xrange(NOVNC_PORTS['START'],
                                         NOVNC_PORTS['END'] + 1):
                if new_novnc_port not in used_ports and new_novnc_port not in NOVNC_PORTS[
                        'EXCLUDE']:
                    break
            else:
                raise CMException('vm_novnc_not_found')

            log.debug(user.id, "Found novnc port: %d" % new_novnc_port)
            vm.novnc_port = new_novnc_port

            if vnc:
                vm.attach_vnc()
            vm.vnc_passwd = password_gen(13,
                                         chars=['letters', 'digits'],
                                         extra_chars='!@#$%^&*()')
            vm.ssh_key = ssh_key
            vm.ssh_username = ssh_username
            vm.user_data = user_data
            vm.save()

            if not reservation_id:
                reservation_id = vm.id

            vm.reservation_id = reservation_id
            vm.save()

            if farm and i == 0:
                farm.head = vm
            vms.append(vm)

            log.debug(user.id, "Attaching disks")
            disk_devs = []
            if i == 0 and disk_list:
                for disk_id in disk_list:
                    log.debug(user.id, 'Attaching disks to first VM')
                    disk = StorageImage.get(user.id, disk_id)
                    if disk.vm != None:
                        raise CMException('image_attached')
                    while disk.disk_dev in disk_devs:
                        disk.disk_dev += 1
                    disk_devs.append(disk.disk_dev)
                    disk.vm = vm
                    disk.save()

            log.debug(user.id, "Attaching CD")
            if i == 0 and iso_list:
                for iso_id in iso_list:
                    log.debug(user.id, 'Attaching iso to first VM')
                    # cd image have not be attached to any other vm
                    iso = IsoImage.get(user.id, iso_id)
                    iso.check_attached()
                    vm.iso_image = iso
                    vm.save()

        for i, vm in enumerate(vms):
            if lease_id != None:
                lease = Lease.objects.get(id=lease_id)

                if lease.user_network.user != user:
                    raise CMException('lease_permission')

                if lease.vm != None:
                    raise CMException('lease_attached')
                lease.vm = vm
                log.debug(user.id, "Attached ip: %s" % lease.address)
            else:
                lease = AvailableNetwork.get_lease(user)
                lease.vm = vm
                lease.save()
                log.debug(user.id, "Attached ip: %s" % lease.address)

            if i == 0 and public_ip_id > 0:
                log.debug(user.id, "Attaching PublicIP")
                try:
                    publicip = PublicIP.objects.filter(user=user).get(
                        id=public_ip_id)
                    publicip.assign(lease)
                    publicip.save()
                except Exception, e:
                    log.exception(user.id, str(e))
                    raise CMException("lease_not_found")
Ejemplo n.º 30
0
Archivo: vm.py Proyecto: cc1-cloud/cc1
    def create(user, name, description, image_id, template_id, public_ip_id, iso_list, disk_list, vnc, groups,
               ssh_key=None, ssh_username=None, count=1,
               farm=None, head_template_id=None, node_id=False, lease_id=None, user_data=None):
        from cm.models.storage_image import StorageImage
        from cm.utils.threads.vm import VMThread

        template = Template.get(template_id)
        image = SystemImage.get(user.id, image_id, groups)

        if image.state != image_states['ok']:
            raise CMException('image_unavailable')

        if farm:
            head_template = Template.get(head_template_id)
            wn_template = template
            user.check_quota([(head_template, 1), (wn_template, count)])
            count += 1
        else:
            user.check_quota([(template, count)])

        vms = []

        reservation_id = None

        for i in range(count):
            # create VM instance
            log.debug(user.id, "Looking for node")
            node = Node.get_free_node(head_template, image, node_id) if farm and i == 0 else Node.get_free_node(template, image, node_id)
            log.info(user.id, 'Selected node: %d' % node.id)
            vm = VM()
            vm.libvirt_id = -1
            if farm:
                if i == 0:
                    vm.name = '%s-head' % name
                    vm.description = 'Farm head'
                    vm.template = head_template
                else:
                    vm.name = '%s-wn%d' % (name, i)
                    vm.description = 'Worker Node'
                    vm.template = wn_template
            else:
                vm.template = template
                vm.description = description
                if count > 1:
                    vm.name = '%s_%d' % (name, i + 1)
                else:
                    vm.name = name
            vm.user = user
            vm.state = vm_states['init']
            vm.start_time = datetime.now()
            vm.system_image = image
            vm.node = node
            vm.save_vm = True
            if farm:
                vm.farm = farm

            # Find first free vnc port
            used_ports = VM.objects.exclude(state__in=[vm_states['closed'], vm_states['erased']]).values_list('vnc_port', flat=True)

            for new_vnc_port in xrange(VNC_PORTS['START'], VNC_PORTS['END'] + 1):
                if new_vnc_port not in used_ports and new_vnc_port not in VNC_PORTS['EXCLUDE']:
                    break
            else:
                raise CMException('vm_vnc_not_found')

            log.debug(user.id, "Found vnc port: %d" % new_vnc_port)
            vm.vnc_port = new_vnc_port

            # Find first free novnc port
            used_ports = VM.objects.exclude(state__in=[vm_states['closed'], vm_states['erased']]).values_list('novnc_port', flat=True)
            for new_novnc_port in xrange(NOVNC_PORTS['START'], NOVNC_PORTS['END'] + 1):
                if new_novnc_port not in used_ports and new_novnc_port not in NOVNC_PORTS['EXCLUDE']:
                    break
            else:
                raise CMException('vm_novnc_not_found')

            log.debug(user.id, "Found novnc port: %d" % new_novnc_port)
            vm.novnc_port = new_novnc_port

            if vnc:
                vm.attach_vnc()
            vm.vnc_passwd = password_gen(13, chars=['letters', 'digits'], extra_chars='!@#$%^&*()')
            vm.ssh_key = ssh_key
            vm.ssh_username = ssh_username
            vm.user_data = user_data
            vm.save()

            if not reservation_id:
                reservation_id = vm.id

            vm.reservation_id = reservation_id
            vm.save()

            if farm and i == 0:
                farm.head = vm
            vms.append(vm)

            log.debug(user.id, "Attaching disks")
            disk_devs = []
            if i == 0 and disk_list:
                for disk_id in disk_list:
                    log.debug(user.id, 'Attaching disks to first VM')
                    disk = StorageImage.get(user.id, disk_id)
                    if disk.vm != None:
                        raise CMException('image_attached')
                    while disk.disk_dev in disk_devs:
                        disk.disk_dev += 1
                    disk_devs.append(disk.disk_dev)
                    disk.vm = vm
                    disk.save()

            log.debug(user.id, "Attaching CD")
            if i == 0 and iso_list:
                for iso_id in iso_list:
                    log.debug(user.id, 'Attaching iso to first VM')
                    # cd image have not be attached to any other vm
                    iso = IsoImage.get(user.id, iso_id)
                    iso.check_attached()
                    vm.iso_image = iso
                    vm.save()

        for i, vm in enumerate(vms):
            if lease_id != None:
                lease = Lease.objects.get(id=lease_id)

                if lease.user_network.user != user:
                    raise CMException('lease_permission')

                if lease.vm != None:
                    raise CMException('lease_attached')
                lease.vm = vm
                log.debug(user.id, "Attached ip: %s" % lease.address)
            else:
                lease = AvailableNetwork.get_lease(user)
                lease.vm = vm
                lease.save()
                log.debug(user.id, "Attached ip: %s" % lease.address)

            if i == 0 and public_ip_id > 0:
                log.debug(user.id, "Attaching PublicIP")
                try:
                    publicip = PublicIP.objects.filter(user=user).get(id=public_ip_id)
                    publicip.assign(lease)
                    publicip.save()
                except Exception, e:
                    log.exception(user.id, str(e))
                    raise CMException("lease_not_found")