Esempio n. 1
0
def create(userid,
           name,
           password,
           flavor,
           image,
           metadata={},
           personality=[],
           networks=None,
           use_backend=None):
    if use_backend is None:
        # Allocate server to a Ganeti backend
        use_backend = allocate_new_server(userid, flavor)

    utils.check_name_length(name, VirtualMachine.VIRTUAL_MACHINE_NAME_LENGTH,
                            "Server name is too long")

    # Create the ports for the server
    ports = create_instance_ports(userid, networks)

    # Fix flavor for archipelago
    disk_template, provider = util.get_flavor_provider(flavor)
    if provider:
        flavor.disk_template = disk_template
        flavor.disk_provider = provider
        flavor.disk_origin = None
        if provider in settings.GANETI_CLONE_PROVIDERS:
            flavor.disk_origin = image['checksum']
            image['backend_id'] = 'null'
    else:
        flavor.disk_provider = None

    # We must save the VM instance now, so that it gets a valid
    # vm.backend_vm_id.
    vm = VirtualMachine.objects.create(name=name,
                                       backend=use_backend,
                                       userid=userid,
                                       imageid=image["id"],
                                       flavor=flavor,
                                       operstate="BUILD")
    log.info("Created entry in DB for VM '%s'", vm)

    # Associate the ports with the server
    for index, port in enumerate(ports):
        associate_port_with_machine(port, vm)
        port.index = index
        port.save()

    for key, val in metadata.items():
        VirtualMachineMetadata.objects.create(meta_key=key,
                                              meta_value=val,
                                              vm=vm)

    # Create the server in Ganeti.
    vm = create_server(vm, ports, flavor, image, personality, password)

    return vm
Esempio n. 2
0
def create(userid, name, password, flavor, image, metadata={},
           personality=[], networks=None, use_backend=None):
    if use_backend is None:
        # Allocate server to a Ganeti backend
        use_backend = allocate_new_server(userid, flavor)

    utils.check_name_length(name, VirtualMachine.VIRTUAL_MACHINE_NAME_LENGTH,
                            "Server name is too long")

    # Create the ports for the server
    ports = create_instance_ports(userid, networks)

    # Fix flavor for archipelago
    disk_template, provider = util.get_flavor_provider(flavor)
    if provider:
        flavor.disk_template = disk_template
        flavor.disk_provider = provider
        flavor.disk_origin = None
        if provider in settings.GANETI_CLONE_PROVIDERS:
            flavor.disk_origin = image['checksum']
            image['backend_id'] = 'null'
    else:
        flavor.disk_provider = None

    # We must save the VM instance now, so that it gets a valid
    # vm.backend_vm_id.
    vm = VirtualMachine.objects.create(name=name,
                                       backend=use_backend,
                                       userid=userid,
                                       imageid=image["id"],
                                       flavor=flavor,
                                       operstate="BUILD")
    log.info("Created entry in DB for VM '%s'", vm)

    # Associate the ports with the server
    for index, port in enumerate(ports):
        associate_port_with_machine(port, vm)
        port.index = index
        port.save()

    for key, val in metadata.items():
        utils.check_name_length(key, VirtualMachineMetadata.KEY_LENGTH,
                                "Metadata key is too long")
        utils.check_name_length(val, VirtualMachineMetadata.VALUE_LENGTH,
                                "Metadata value is too long")
        VirtualMachineMetadata.objects.create(
            meta_key=key,
            meta_value=val,
            vm=vm)

    # Create the server in Ganeti.
    vm = create_server(vm, ports, flavor, image, personality, password)

    return vm
Esempio n. 3
0
def do_create_server(userid, name, password, flavor, image, metadata={},
                     personality=[], network=None, backend=None):
    # Fix flavor for archipelago
    disk_template, provider = util.get_flavor_provider(flavor)
    if provider:
        flavor.disk_template = disk_template
        flavor.disk_provider = provider
        flavor.disk_origin = image['checksum']
        image['backend_id'] = 'null'
    else:
        flavor.disk_provider = None
        flavor.disk_origin = None

    try:
        if backend is None:
            # Allocate backend to host the server.
            backend_allocator = BackendAllocator()
            backend = backend_allocator.allocate(userid, flavor)
            if backend is None:
                log.error("No available backend for VM with flavor %s", flavor)
                raise faults.ServiceUnavailable("No available backends")

        if network is None:
            # Allocate IP from public network
            (network, address) = util.get_public_ip(backend)
        else:
            address = util.get_network_free_address(network)

        # We must save the VM instance now, so that it gets a valid
        # vm.backend_vm_id.
        vm = VirtualMachine.objects.create(
            name=name,
            backend=backend,
            userid=userid,
            imageid=image["id"],
            flavor=flavor,
            action="CREATE")

        log.info("Created entry in DB for VM '%s'", vm)

        # Create VM's public NIC. Do not wait notification form ganeti hooks to
        # create this NIC, because if the hooks never run (e.g. building error)
        # the VM's public IP address will never be released!
        nic = NetworkInterface.objects.create(machine=vm, network=network,
                                              index=0, ipv4=address,
                                              state="BUILDING")

        # Also we must create the VM metadata in the same transaction.
        for key, val in metadata.items():
            VirtualMachineMetadata.objects.create(
                meta_key=key,
                meta_value=val,
                vm=vm)
        # Issue commission to Quotaholder and accept it since at the end of
        # this transaction the VirtualMachine object will be created in the DB.
        # Note: the following call does a commit!
        quotas.issue_and_accept_commission(vm)
    except:
        transaction.rollback()
        raise
    else:
        transaction.commit()

    try:
        vm = VirtualMachine.objects.select_for_update().get(id=vm.id)
        # dispatch server created signal needed to trigger the 'vmapi', which
        # enriches the vm object with the 'config_url' attribute which must be
        # passed to the Ganeti job.
        server_created.send(sender=vm, created_vm_params={
            'img_id': image['backend_id'],
            'img_passwd': password,
            'img_format': str(image['format']),
            'img_personality': json.dumps(personality),
            'img_properties': json.dumps(image['metadata']),
        })

        jobID = create_instance(vm, nic, flavor, image)
        # At this point the job is enqueued in the Ganeti backend
        vm.backendopcode = "OP_INSTANCE_CREATE"
        vm.backendjobid = jobID
        vm.save()
        transaction.commit()
        log.info("User %s created VM %s, NIC %s, Backend %s, JobID %s",
                 userid, vm, nic, backend, str(jobID))
    except:
        # If an exception is raised, then the user will never get the VM id.
        # In order to delete it from DB and release it's resources, we
        # mock a successful OP_INSTANCE_REMOVE job.
        process_op_status(vm=vm,
                          etime=datetime.datetime.now(),
                          jobid=-0,
                          opcode="OP_INSTANCE_REMOVE",
                          status="success",
                          logmsg="Reconciled eventd: VM creation failed.")
        raise

    return vm
Esempio n. 4
0
def do_create_server(userid,
                     name,
                     password,
                     flavor,
                     image,
                     metadata={},
                     personality=[],
                     network=None,
                     backend=None):
    # Fix flavor for archipelago
    disk_template, provider = util.get_flavor_provider(flavor)
    if provider:
        flavor.disk_template = disk_template
        flavor.disk_provider = provider
        flavor.disk_origin = image['checksum']
        image['backend_id'] = 'null'
    else:
        flavor.disk_provider = None
        flavor.disk_origin = None

    try:
        if backend is None:
            # Allocate backend to host the server.
            backend_allocator = BackendAllocator()
            backend = backend_allocator.allocate(userid, flavor)
            if backend is None:
                log.error("No available backend for VM with flavor %s", flavor)
                raise faults.ServiceUnavailable("No available backends")

        if network is None:
            # Allocate IP from public network
            (network, address) = util.get_public_ip(backend)
            nic = {'ip': address, 'network': network.backend_id}
        else:
            address = util.get_network_free_address(network)

        # We must save the VM instance now, so that it gets a valid
        # vm.backend_vm_id.
        vm = VirtualMachine.objects.create(name=name,
                                           backend=backend,
                                           userid=userid,
                                           imageid=image["id"],
                                           flavor=flavor,
                                           action="CREATE")

        # Create VM's public NIC. Do not wait notification form ganeti hooks to
        # create this NIC, because if the hooks never run (e.g. building error)
        # the VM's public IP address will never be released!
        NetworkInterface.objects.create(machine=vm,
                                        network=network,
                                        index=0,
                                        ipv4=address,
                                        state="BUILDING")

        log.info("Created entry in DB for VM '%s'", vm)

        # dispatch server created signal
        server_created.send(sender=vm,
                            created_vm_params={
                                'img_id': image['backend_id'],
                                'img_passwd': password,
                                'img_format': str(image['format']),
                                'img_personality': json.dumps(personality),
                                'img_properties':
                                json.dumps(image['metadata']),
                            })

        # Also we must create the VM metadata in the same transaction.
        for key, val in metadata.items():
            VirtualMachineMetadata.objects.create(meta_key=key,
                                                  meta_value=val,
                                                  vm=vm)
        # Issue commission to Quotaholder and accept it since at the end of
        # this transaction the VirtualMachine object will be created in the DB.
        # Note: the following call does a commit!
        quotas.issue_and_accept_commission(vm)
    except:
        transaction.rollback()
        raise
    else:
        transaction.commit()

    try:
        jobID = create_instance(vm, nic, flavor, image)
        # At this point the job is enqueued in the Ganeti backend
        vm.backendjobid = jobID
        vm.save()
        transaction.commit()
        log.info("User %s created VM %s, NIC %s, Backend %s, JobID %s", userid,
                 vm, nic, backend, str(jobID))
    except GanetiApiError as e:
        log.exception("Can not communicate to backend %s: %s.", backend, e)
        # Failed while enqueuing OP_INSTANCE_CREATE to backend. Restore
        # already reserved quotas by issuing a negative commission
        vm.operstate = "ERROR"
        vm.backendlogmsg = "Can not communicate to backend."
        vm.deleted = True
        vm.save()
        quotas.issue_and_accept_commission(vm, delete=True)
        raise
    except:
        transaction.rollback()
        raise

    return vm