diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index fc35db4301..6133069f75 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -643,6 +643,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, { Nebula& nd = Nebula::instance(); DispatchManager * dm = nd.get_dm(); + DatastorePool * dspool = nd.get_dspool(); VirtualMachine * vm; @@ -652,7 +653,9 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, int cluster_id; string ds_location; bool is_public_cloud; - PoolObjectAuth host_perms; + + PoolObjectAuth host_perms, ds_perms; + PoolObjectAuth * auth_ds_perms; string tm_mad; @@ -691,16 +694,9 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, } // ------------------------------------------------------------------------ - // Authorize request + // Get information about the system DS to use (tm_mad & permissions) // ------------------------------------------------------------------------ - auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op); - - if (auth == false) - { - return; - } - if ((vm = get_vm(id, att)) == 0) { return; @@ -716,10 +712,6 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, vm->unlock(); - // ------------------------------------------------------------------------ - // Get information about the system DS to use (tm_mad) - // ------------------------------------------------------------------------ - if (is_public_cloud) // Set ds_id to -1 and tm_mad empty(). This is used by { // by VirtualMachine::get_host_is_cloud() ds_id = -1; @@ -758,6 +750,41 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, } } + if (ds_id == -1) + { + auth_ds_perms = 0; + } + else + { + Datastore * ds = dspool->get(ds_id, true); + + if (ds == 0 ) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::DATASTORE), ds_id), + att); + + return; + } + + ds->get_permissions(ds_perms); + + ds->unlock(); + + auth_ds_perms = &ds_perms; + } + + // ------------------------------------------------------------------------ + // Authorize request + // ------------------------------------------------------------------------ + + auth = vm_authorization(id, 0, 0, att, &host_perms, auth_ds_perms, auth_op); + + if (auth == false) + { + return; + } + // ------------------------------------------------------------------------ // Check request consistency: // - VM States are right diff --git a/src/scheduler/src/sched/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc index f152d2ae12..f718df25b5 100644 --- a/src/scheduler/src/sched/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -617,14 +617,16 @@ static bool match_host(AclXML * acls, VirtualMachineXML* vm, int vmem, int vcpu, * @param vm the virtual machine * @param vdisk vm requirement * @param ds to evaluate vm assgiment + * @param n_auth number of ds authorized for the user, incremented if needed * @param n_error number of requirement errors, incremented if needed * @param n_matched number of system ds that fullfil VM sched_requirements * @param n_fits number of system ds with capacity that fits the VM requirements * @param error, string describing why the host is not valid * @return true for a positive match */ -static bool match_system_ds(VirtualMachineXML* vm, long long vdisk, - DatastoreXML * ds, int& n_error, int& n_fits, int &n_matched, string &error) +static bool match_system_ds(AclXML * acls, VirtualMachineXML* vm, long long vdisk, + DatastoreXML * ds, int& n_auth, int& n_error, int& n_fits, int &n_matched, + string &error) { // ------------------------------------------------------------------------- // Check datastore capacity for shared systems DS (non-shared will be @@ -638,6 +640,31 @@ static bool match_system_ds(VirtualMachineXML* vm, long long vdisk, n_fits++; + // ------------------------------------------------------------------------- + // Check if user is authorized + // ------------------------------------------------------------------------- + if ( vm->get_uid() != 0 && vm->get_gid() != 0 ) + { + PoolObjectAuth dsperms; + + dsperms.oid = ds->get_oid(); + dsperms.cid = ds->get_cid(); + dsperms.obj_type = PoolObjectSQL::DATASTORE; + + // Only include the VM group ID + + set gids; + gids.insert(vm->get_gid()); + + if ( !acls->authorize(vm->get_uid(), gids, dsperms, AuthRequest::USE)) + { + error = "Permission denied."; + return false; + } + } + + n_auth++; + // ------------------------------------------------------------------------- // Evaluate VM requirements // ------------------------------------------------------------------------- @@ -840,6 +867,7 @@ void Scheduler::match_schedule() // --------------------------------------------------------------------- n_resources = 0; + n_auth = 0; n_matched = 0; n_error = 0; n_fits = 0; @@ -848,7 +876,8 @@ void Scheduler::match_schedule() { ds = static_cast(h_it->second); - if (match_system_ds(vm, vm_disk, ds, n_error, n_fits, n_matched, m_error)) + if (match_system_ds(acls, vm, vm_disk, ds, n_auth, n_error, n_fits, + n_matched, m_error)) { vm->add_match_datastore(ds->get_oid()); @@ -890,6 +919,10 @@ void Scheduler::match_schedule() vm->log(oss.str()); } + else if (n_auth == 0) + { + vm->log("User is not authorized to use any system datastore"); + } else if (n_fits == 0) { vm->log("No system datastore with enough capacity for the VM");