Ejemplo n.º 1
0
def start_vm(username,
             cloudname,
             count=1,
             flavorname=None,
             flavorid=None,
             imagename=None,
             imageid=None,
             groupname=None,
             servername=None):
    '''
    create a VM on a cloud for a user
    
    If flavor or image is provided, the function will check the flavor, image 
    existence;
    it's better to check cloud active status before use this function
    

    TODO: this function should be relocated into a class;
          what if fail to create, how to acknowledge it. no return now because
          of using celery;
          missing security group
        
    :param username: user name
    :type username: string
    :param cloudname: cloud name
    :type cloudname: string
    :param count: give the number of vms to start at one call of this function,
                  the default is 1
    :type count: int
    :param flavorname: flavor name, if flavor name or id is not provided, the
                       function will try to find the user specified default 
                       flavor
    :type flavorname: string
    :param flavorid: flavor id, if flavor name or id is not provided, the
                     function will try to find the user specified default 
                     flavor
    :type flavorid: string
    :param imagename: image name, if image name or id is not provided, the
                      function will try to find the user specified default 
                      image
    :type imagename: string
    :param imageid: image id, if image name or id is not provided, the
                     function will try to find the user specified default 
                     image
    :type imageid: string
    :param groupname: user can specify groupname of the VM, this groupname will
                      be included in the metadata of the VM
    :type groupname: string
    :param servername: user can provide the name of the VM, which will replace 
                       the default prefix+index form
    :type servername: string
    :return:  False if error occurs
    :rtype: boolean
    
    '''
    # Changed scope of this import - hyungro lee 12/01/2014
    from cloudmesh.experiment.group_usage import add_vm_to_group_while_creating

    mongo = cm_mongo()
    userobj = cm_user()
    cloudobj = CloudManage()
    mongo.activate(cm_user_id=username, names=[cloudname])
    userinfo = userobj.info(username)
    key = None
    vm_image_id = None
    vm_flavor_id = None

    error = ''

    # -------------------------
    # refresh server flavor or image
    to_refresh = ["servers"]

    if flavorname is not None or flavorid is not None:
        to_refresh.append("flavors")
    if imagename is not None or imageid is not None:
        to_refresh.append("images")
    if to_refresh != []:
        mongo.refresh(username, names=[cloudname], types=to_refresh)

    # -------------------------
    # get exist VM names list, to prevent names duplicate
    serverdata = mongo.servers(
        clouds=[cloudname],
        cm_user_id=username)[cloudname]
    servers_names_list = []
    for k, v in serverdata.iteritems():
        servers_names_list.append(v['name'])

    # -------------------------
    # flavor handler
    if flavorname is not None or flavorid is not None:
        flavordata = mongo.flavors(
            clouds=[cloudname], cm_user_id=username)[cloudname]
        same_name_count = 0
        for k, v in flavordata.iteritems():
            if flavorname is not None:
                if flavorname == v['name']:
                    vm_flavor_id = k
                    same_name_count = same_name_count + 1
            else:
                if flavorid == k:
                    vm_flavor_id = k
                    break
        if vm_flavor_id is None:
            error = error + "The flavor you provide doesn't exist. "
        if same_name_count > 1:
            error = error + "There are more than one flavor with the name you provide" \
                            "please use flavorid instead or select one by command cloud" \
                            "set flavor [CLOUD]. "
    else:
        try:
            vm_flavor_id = userinfo["defaults"]["flavors"][cloudname]
        except:
            pass
        if vm_flavor_id in [None, 'none']:
            error = error + \
                    "Please specify a default flavor(command: cloud set flavor [CLOUD]). "
    # -------------------------
    # image handler
    if imagename is not None or imageid is not None:
        imagedata = mongo.images(
            clouds=[cloudname], cm_user_id=username)[cloudname]
        same_name_count = 0
        for k, v in imagedata.iteritems():
            if imagename is not None:
                if imagename == v['name']:
                    vm_image_id = k
                    same_name_count = same_name_count + 1
            else:
                if imageid == k:
                    vm_image_id = k
                    break
        if vm_image_id is None:
            error = error + "The image you provide doesn't exist. "
        if same_name_count > 1:
            error = error + "There are more than one image with the name you provide" \
                            "please use imageid instead or select one by command cloud" \
                            "set image [CLOUD]. "
    else:
        try:
            vm_image_id = userinfo["defaults"]["images"][cloudname]
        except:
            pass
        if vm_image_id in [None, 'none']:
            error = error + \
                    "Please specify a default image(command: cloud set flavor [CLOUD]). "

    # -------------------------
    # key handler
    if "key" in userinfo["defaults"]:
        key = userinfo["defaults"]["key"]
    elif len(userinfo["keys"]["keylist"].keys()) > 0:
        key = userinfo["keys"]["keylist"].keys()[0]

    if key:
        keycontent = userinfo["keys"]["keylist"][key]
        if keycontent.startswith('key '):
            keycontent = keycontent[4:]
        cm_keys_mongo(username).check_register_key(username, cloudname, key, keycontent)
        keynamenew = _keyname_sanitation(username, key)
    else:
        error = error + \
                "No sshkey found. Please Upload one"
    # -------------------------

    if error != '':
        Console.error(error)
        return False
    # -------------------------
    metadata = {'cm_owner': username}
    if groupname:
        metadata['cm_group'] = groupname

    tmpnamefl = cloudobj.get_flavors(
        cloudname=cloudname, getone=True, id=vm_flavor_id)['name']
    tmpnameim = cloudobj.get_images(
        cloudname=cloudname, getone=True, id=vm_image_id)['name']

    while count > 0:
        userinfo = userobj.info(username)
        if servername:
            prefix = ''
            index = ''
            givenvmname = servername
            tmpnameser = servername
        else:
            prefix = userinfo["defaults"]["prefix"]
            index = userinfo["defaults"]["index"]
            givenvmname = None
            tmpnameser = prefix + '_' + str(index)

        # ------------------------
        # do not allow server name duplicate
        if tmpnameser in servers_names_list:
            Console.error("vm name '{0}' exists, please "
                          "use other names or delete it first".format(tmpnameser))
            if not servername:
                userobj.set_default_attribute(username, "index", int(index) + 1)
            count = count - 1
            continue
        # ------------------------
        # vm start procedure

        banner("Starting vm->{0} on cloud->{1} using image->{2}, flavor->{3}, key->{4}"
               .format(tmpnameser, cloudname, tmpnameim, tmpnamefl, keynamenew))

        useQueue = False
        if useQueue:
            result = mongo.vm_create_queue(cloudname,
                                           prefix,
                                           index,
                                           vm_flavor_id,
                                           vm_image_id,
                                           keynamenew,
                                           meta=metadata,
                                           cm_user_id=username,
                                           givenvmname=givenvmname)
            print("job status:", result.state)
        else:
            result = mongo.vm_create(cloudname,
                                     prefix,
                                     index,
                                     vm_flavor_id,
                                     vm_image_id,
                                     keynamenew,
                                     meta=metadata,
                                     cm_user_id=username,
                                     givenvmname=givenvmname)
            if "server" in result and "adminPass" in result["server"]:
                result["server"]["adminPass"] = "******"
            pprint(result)

        # ------------------------
        # add it to the group in database if groupname provided
        if groupname:
            try:
                add_vm_to_group_while_creating(username, groupname, tmpnameser)
            except Exception, err:
                Console.error(str(err))
                return

        # ------------------------
        # increase index if it is used
        if not servername:
            userobj.set_default_attribute(username, "index", int(index) + 1)
        # ------------------------
        servers_names_list.append(tmpnameser)

        count = count - 1