1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-02 09:47:00 +03:00

Merge branch 'feature-1727'

This commit is contained in:
Ruben S. Montero 2015-07-29 12:33:57 +02:00
commit 6fb47ac1be
65 changed files with 7946 additions and 7089 deletions

View File

@ -181,9 +181,8 @@ public:
* @param disk
* @param inherit_attrs Attributes to be inherited from the DS template
* into the disk
* @return 0 on success
*/
int disk_attribute(
void disk_attribute(
VectorAttribute * disk,
const vector<string>& inherit_attrs);

View File

@ -416,9 +416,8 @@ public:
* @param inherit_attrs Attributes to be inherited from the image template
* into the disk
*
* @return 0 on success, -1 otherwise
*/
int disk_attribute( VectorAttribute * disk,
void disk_attribute(VectorAttribute * disk,
ImageType& img_type,
string& dev_prefix,
const vector<string>& inherit_attrs);

View File

@ -150,7 +150,8 @@ public:
}
/**
* Generates a DISK attribute for VM templates using the Image metadata
* Generates a DISK attribute for VM templates using the Image metadata.
* If the disk uses an Image, it tries to acquire it.
*
* @param disk the disk to be generated
* @param disk_id the id for this disk
@ -164,7 +165,7 @@ public:
*
* @return 0 on success, -1 otherwise
*/
int disk_attribute(int vm_id,
int acquire_disk( int vm_id,
VectorAttribute * disk,
int disk_id,
Image::ImageType& img_type,
@ -173,6 +174,19 @@ public:
int& image_id,
Snapshots ** snaps,
string& error_str);
/**
* Generates a DISK attribute for VM templates using the Image metadata
*
* @param disk the disk to be generated
* @param disk_id the id for this disk
* @param uid of VM owner (to look for the image id within its images)
*
*/
void disk_attribute(VectorAttribute * disk,
int disk_id,
int uid);
/**
* Generates an Authorization token for the DISK attribute
* @param disk the disk to be authorized

View File

@ -402,7 +402,7 @@ public:
*/
static string local_db_version()
{
return "4.13.80";
return "4.13.85";
}
/**

View File

@ -22,14 +22,14 @@
/**
* VM Quotas, defined as:
* VM = [
* VMS = <Max. number of VMs>
* MEMORY = <Max. number of MB requested by VMs>
* CPU = <Max. number of CPU units requested by VMs>
* VOLATILE_SIZE = <Max. number of volatile disk MB>
* VMS_USED = Current number of VMs
* MEMORY_USED = Overall Memory requested
* CPU_USED = Overall CPU requested
* VOLATILE_SIZE_USED = <Max. number of volatile disk MB>
* VMS = <Max. number of VMs>
* MEMORY = <Max. number of MB requested by VMs>
* CPU = <Max. number of CPU units requested by VMs>
* SYSTEM_DISK_SIZE = <Max. number of system disk MB>
* VMS_USED = Current number of VMs
* MEMORY_USED = Overall Memory requested
* CPU_USED = Overall CPU requested
* SYSTEM_DISK_SIZE_USED = Overall system disk requested
* ]
*
* 0 = unlimited, default if missing

View File

@ -40,7 +40,7 @@ protected:
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& _paramList,
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
/* -------------------------------------------------------------------- */
@ -93,6 +93,11 @@ public:
};
~TemplateInfo(){};
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */

View File

@ -79,7 +79,7 @@ public:
* @param size_mb of the snapshot (virtual size)
* @return id of the new snapshot
*/
int create_snapshot(const string& name, unsigned int size_mb);
int create_snapshot(const string& name, long long size_mb);
/**
* Check if an snapshot can be deleted (no children, no active)
@ -172,14 +172,14 @@ public:
/**
* @return total snapshot size (virtual) in mb
*/
unsigned int get_total_size() const;
long long get_total_size() const;
/**
* Get the size (virtual) in mb of the given snapshot
* @param id of the snapshot
* @return size or 0 if not found
*/
unsigned int get_snapshot_size(int id) const;
long long get_snapshot_size(int id) const;
/**
* Get Attribute from the given snapshot

View File

@ -37,6 +37,17 @@ public:
*/
string& to_xml(string& xml) const;
/**
* Function to print the VMTemplate object into a string in XML format
* @param xml the resulting XML string
* @param tmpl a template to replace the internal obj_template. It is only
* used to create the resulting xml string, the internal obj_template is
* not altered
* @return a reference to the generated string
*/
string& to_xml(string& xml, const Template* tmpl) const;
// ------------------------------------------------------------------------
// Template Contents
// ------------------------------------------------------------------------

View File

@ -1273,9 +1273,16 @@ public:
bool is_imported() const;
/**
* Return the total SIZE of volatile disks
* Return the total disk SIZE that the VM instance needs in the system DS
*/
static long long get_volatile_disk_size(Template * tmpl);
static long long get_system_disk_size(Template * tmpl);
/**
* Returns the disk CLONE_TARGET or LN_TARGET
* @param disk
* @return NONE, SYSTEM, SELF. Empty string if it could not be determined
*/
static string disk_target(const VectorAttribute * disk);
/**
* Returns a set of the security group IDs in use in this VM
@ -1367,6 +1374,15 @@ public:
AuthRequest& ar,
VirtualMachineTemplate *tmpl);
/**
* Adds extra info to the given template:
* DISK/IMAGE_ID and SIZE
* @param uid for template owner
* @param tmpl the virtual machine template
*/
static void disk_extended_info(int uid,
VirtualMachineTemplate *tmpl);
// -------------------------------------------------------------------------
// Hotplug related functions
// -------------------------------------------------------------------------
@ -1552,15 +1568,14 @@ public:
int revert_disk_snapshot(int disk_id, int snap_id);
/**
* Deletes the snap_id from the list, test_delete_disk_snapshot *MUST* be
* called before actually deleting the snapshot.
* Deletes the snap_id from the list
* @param disk_id of the disk
* @param snap_id of the snapshot
* @param type of quota used by this snapshot
* @param quotas template with snapshot usage
* @param ds_quotas template with snapshot usage for the DS quotas
* @param vm_quotas template with snapshot usage for the VM quotas
*/
void delete_disk_snapshot(int disk_id, int snap_id, Quotas::QuotaType& type,
Template **quotas);
void delete_disk_snapshot(int disk_id, int snap_id, Template **ds_quotas,
Template **vm_quotas);
/**
* Get information about the disk to take the snapshot from

View File

@ -1232,7 +1232,8 @@ ONEDB_LOCAL_MIGRATOR_FILES="src/onedb/local/4.5.80_to_4.7.80.rb \
src/onedb/local/4.7.80_to_4.9.80.rb \
src/onedb/local/4.9.80_to_4.10.3.rb \
src/onedb/local/4.10.3_to_4.11.80.rb \
src/onedb/local/4.11.80_to_4.13.80.rb"
src/onedb/local/4.11.80_to_4.13.80.rb \
src/onedb/local/4.13.80_to_4.13.85.rb"
ONEDB_PATCH_FILES="src/onedb/patches/4.14_monitoring.rb"

View File

@ -65,8 +65,8 @@
<xs:element name="MEMORY_USED" type="xs:string"/>
<xs:element name="VMS" type="xs:string"/>
<xs:element name="VMS_USED" type="xs:string"/>
<xs:element name="VOLATILE_SIZE" type="xs:string"/>
<xs:element name="VOLATILE_SIZE_USED" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE_USED" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -76,8 +76,8 @@
<xs:element name="MEMORY_USED" type="xs:string"/>
<xs:element name="VMS" type="xs:string"/>
<xs:element name="VMS_USED" type="xs:string"/>
<xs:element name="VOLATILE_SIZE" type="xs:string"/>
<xs:element name="VOLATILE_SIZE_USED" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE_USED" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -64,8 +64,8 @@
<xs:element name="MEMORY_USED" type="xs:string"/>
<xs:element name="VMS" type="xs:string"/>
<xs:element name="VMS_USED" type="xs:string"/>
<xs:element name="VOLATILE_SIZE" type="xs:string"/>
<xs:element name="VOLATILE_SIZE_USED" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE_USED" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -76,8 +76,8 @@
<xs:element name="MEMORY_USED" type="xs:string"/>
<xs:element name="VMS" type="xs:string"/>
<xs:element name="VMS_USED" type="xs:string"/>
<xs:element name="VOLATILE_SIZE" type="xs:string"/>
<xs:element name="VOLATILE_SIZE_USED" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE" type="xs:string"/>
<xs:element name="SYSTEM_DISK_SIZE_USED" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -117,8 +117,8 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
"CPU_USED" => "0",
"MEMORY" => OneQuotaHelper::LIMIT_DEFAULT,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE_USED" => "0"
}
quotas[d['ID']] = q
@ -154,8 +154,8 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
"CPU_USED" => "0",
"MEMORY" => OneQuotaHelper::LIMIT_DEFAULT,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE_USED" => "0"
}
quotas[d['ID']] = q
@ -194,8 +194,8 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
"CPU_USED" => "0",
"MEMORY" => OneQuotaHelper::LIMIT_DEFAULT,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE_USED" => "0"
}
quotas[d['ID']] = q

View File

@ -34,10 +34,10 @@ class OneQuotaHelper
# ]
#
# VM = [
# VMS = <Max. number of VMs>
# MEMORY = <Max. allocated memory (MB)>
# CPU = <Max. allocated CPU>
# VOLATILE_SIZE = <Max. allocated volatile disks (MB)>
# VMS = <Max. number of VMs>
# MEMORY = <Max. allocated memory (MB)>
# CPU = <Max. allocated CPU>
# SYSTEM_DISK_SIZE = <Max. allocated system disk (MB)>
# ]
#
# NETWORK = [
@ -216,8 +216,8 @@ class OneQuotaHelper
"CPU_USED" => "0",
"MEMORY" => limit,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => limit,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => limit,
"SYSTEM_DISK_SIZE_USED" => "0"
}]
end
@ -273,20 +273,20 @@ class OneQuotaHelper
end
end
column :"VOLATILE_SIZE", "", :right, :size=>20 do |d|
column :"SYSTEM_DISK_SIZE", "", :right, :size=>20 do |d|
if !d.nil?
elem = 'VOLATILE_SIZE'
elem = 'SYSTEM_DISK_SIZE'
limit = d[elem]
limit = helper.get_default_limit(
limit, "VM_QUOTA/VM/#{elem}")
if limit == LIMIT_UNLIMITED
"%8s / -" % [
OpenNebulaHelper.unit_to_str(d["VOLATILE_SIZE_USED"].to_i,{},"M")
OpenNebulaHelper.unit_to_str(d["SYSTEM_DISK_SIZE_USED"].to_i,{},"M")
]
else
"%8s / %8s" % [
OpenNebulaHelper.unit_to_str(d["VOLATILE_SIZE_USED"].to_i,{},"M"),
OpenNebulaHelper.unit_to_str(d["SYSTEM_DISK_SIZE_USED"].to_i,{},"M"),
OpenNebulaHelper.unit_to_str(limit.to_i,{},"M")
]
end

View File

@ -43,6 +43,13 @@ EOT
:description => "Integrate userdata into the EC2 section"
}
EXTENDED={
:name => "extended",
:large => "--extended",
:description => "Process the template and included extended "+
"information, such as the SIZE for each DISK"
}
def self.rname
"VMTEMPLATE"
end
@ -51,6 +58,26 @@ EOT
"onetemplate.yaml"
end
def show_resource(id, options)
resource = retrieve_resource(id)
if !options[:extended].nil?
rc = resource.info(options[:extended])
else
rc = resource.info
end
return -1, rc.message if OpenNebula.is_error?(rc)
if options[:xml]
return 0, resource.to_xml(true)
else
format_resource(resource, options)
return 0
end
end
def format_pool(options)
config_file = self.class.table_conf

View File

@ -260,8 +260,8 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
"CPU_USED" => "0",
"MEMORY" => OneQuotaHelper::LIMIT_DEFAULT,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE_USED" => "0"
}
quotas[d['ID']] = q
@ -299,8 +299,8 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
"CPU_USED" => "0",
"MEMORY" => OneQuotaHelper::LIMIT_DEFAULT,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE_USED" => "0"
}
quotas[d['ID']] = q
@ -341,8 +341,8 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
"CPU_USED" => "0",
"MEMORY" => OneQuotaHelper::LIMIT_DEFAULT,
"MEMORY_USED" => "0",
"VOLATILE_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"VOLATILE_SIZE_USED" => "0"
"SYSTEM_DISK_SIZE" => OneQuotaHelper::LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE_USED" => "0"
}
quotas[d['ID']] = q

View File

@ -319,7 +319,9 @@ cmd=CommandParser::CmdParser.new(ARGV) do
Shows information for the given Template
EOT
command :show, show_desc, :templateid, :options=>OpenNebulaHelper::XML do
command :show, show_desc, :templateid,
:options=>[OpenNebulaHelper::XML,OneTemplateHelper::EXTENDED] do
helper.show_resource(args[0],options)
end

View File

@ -101,7 +101,7 @@ int Datastore::enable(bool enable, string& error_str)
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Datastore::disk_attribute(
void Datastore::disk_attribute(
VectorAttribute * disk,
const vector<string>& inherit_attrs)
{
@ -148,8 +148,6 @@ int Datastore::disk_attribute(
disk->replace(*it, inherit_val);
}
}
return 0;
}
/* ************************************************************************ */

View File

@ -488,7 +488,7 @@ int Image::from_xml(const string& xml)
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::disk_attribute( VectorAttribute * disk,
void Image::disk_attribute( VectorAttribute * disk,
ImageType& img_type,
string& dev_prefix,
const vector<string>& inherit_attrs)
@ -500,19 +500,20 @@ int Image::disk_attribute( VectorAttribute * disk,
bool ro;
ostringstream iid;
vector<string>::const_iterator it;
img_type = type;
target = disk->vector_value("TARGET");
driver = disk->vector_value("DRIVER");
dev_prefix = disk->vector_value("DEV_PREFIX");
iid << oid;
long long size = -1;
long long snap_size;
string template_target;
string template_driver;
string template_ptype;
string template_size;
get_template_attribute("TARGET", template_target);
get_template_attribute("DRIVER", template_driver);
@ -546,9 +547,20 @@ int Image::disk_attribute( VectorAttribute * disk,
// BASE DISK ATTRIBUTES
//--------------------------------------------------------------------------
disk->replace("IMAGE", name);
disk->replace("IMAGE_ID", iid.str());
disk->replace("IMAGE_ID", oid);
disk->replace("SOURCE", source);
disk->replace("SIZE", size_mb);
if ( disk->vector_value("SIZE", size) == 0 && size != size_mb)
{
disk->replace("ORIGINAL_SIZE", size_mb);
}
else
{
disk->replace("SIZE", size_mb);
}
snap_size = snapshots.get_total_size();
disk->replace("DISK_SNAPSHOT_TOTAL_SIZE", snap_size);
if (driver.empty() && !template_driver.empty())//DRIVER in Image,not in DISK
{
@ -570,7 +582,7 @@ int Image::disk_attribute( VectorAttribute * disk,
}
else
{
disk->replace("READONLY", "NO");
disk->replace("READONLY", false);
}
}
@ -663,8 +675,6 @@ int Image::disk_attribute( VectorAttribute * disk,
disk->replace(*it, inherit_val);
}
}
return 0;
}
/* ------------------------------------------------------------------------ */

View File

@ -498,7 +498,7 @@ int ImageManager::delete_image(int iid, string& error_str)
ipool->update(img);
}
unsigned int snap_size = (img->get_snapshots()).get_total_size();
long long snap_size = (img->get_snapshots()).get_total_size();
img->unlock();

View File

@ -693,8 +693,8 @@ static void snap_delete_action(istringstream& is,
ostringstream oss;
string info;
unsigned int snap_size;
int ds_id, uid, gid;
long long snap_size;
int ds_id, uid, gid;
Image * image = ipool->get(id, true);
@ -753,7 +753,7 @@ static void snap_delete_action(istringstream& is,
Template quotas;
quotas.add("DATASTORE", ds_id);
quotas.add("SIZE", (long long) snap_size);
quotas.add("SIZE", snap_size);
quotas.add("IMAGES",0 );
Quotas::ds_del(uid, gid, &quotas);
@ -828,8 +828,8 @@ static void snap_flatten_action(istringstream& is,
ostringstream oss;
string info;
unsigned int snap_size;
int ds_id, uid, gid;
long long snap_size;
int ds_id, uid, gid;
Image * image = ipool->get(id, true);
@ -876,7 +876,7 @@ static void snap_flatten_action(istringstream& is,
Template quotas;
quotas.add("DATASTORE", ds_id);
quotas.add("SIZE", (long long) snap_size);
quotas.add("SIZE", snap_size);
quotas.add("IMAGES",0 );
Quotas::ds_del(uid, gid, &quotas);

View File

@ -307,7 +307,7 @@ int ImagePool::get_disk_id(const string& id_s)
/* -------------------------------------------------------------------------- */
int ImagePool::disk_attribute(int vm_id,
int ImagePool::acquire_disk( int vm_id,
VectorAttribute * disk,
int disk_id,
Image::ImageType& img_type,
@ -410,8 +410,37 @@ int ImagePool::disk_attribute(int vm_id,
DatastorePool * ds_pool = nd.get_dspool();
Datastore * ds;
long long size = 0;
bool has_size = (disk->vector_value("SIZE", size) == 0);
if (has_size && img->is_persistent() && size != img->get_size())
{
img->unlock();
imagem->release_image(vm_id, iid, false);
oss << "SIZE attribute is not supported for persistent image ["
<< img->get_oid() << "].";
error_str = oss.str();
return -1;
}
if (has_size && size < img->get_size())
{
img->unlock();
imagem->release_image(vm_id, iid, false);
oss << "SIZE of " << size << "MB is less than the image ["
<< img->get_oid() << "] size of " << img->get_size() << "MB.";
error_str = oss.str();
return -1;
}
iid = img->get_oid();
rc = img->disk_attribute(disk, img_type, dev_prefix, inherit_image_attrs);
img->disk_attribute(disk, img_type, dev_prefix, inherit_image_attrs);
image_id = img->get_oid();
datastore_id = img->get_ds_id();
@ -424,17 +453,6 @@ int ImagePool::disk_attribute(int vm_id,
img->unlock();
if (rc == -1)
{
imagem->release_image(vm_id, iid, false);
error_str = "Unknown internal error";
delete *snap;
*snap = 0;
return -1;
}
ds = ds_pool->get(datastore_id, true);
if ( ds == 0 )
@ -453,8 +471,7 @@ int ImagePool::disk_attribute(int vm_id,
ds->unlock();
}
oss << disk_id;
disk->replace("DISK_ID",oss.str());
disk->replace("DISK_ID", disk_id);
return rc;
}
@ -462,11 +479,71 @@ int ImagePool::disk_attribute(int vm_id,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImagePool::disk_attribute(
VectorAttribute * disk,
int disk_id,
int uid)
{
string source;
Image * img = 0;
int datastore_id;
string dev_prefix;
Image::ImageType img_type;
ostringstream oss;
Nebula& nd = Nebula::instance();
DatastorePool * ds_pool = nd.get_dspool();
Datastore * ds;
if (!(source = disk->vector_value("IMAGE")).empty())
{
int uiid = get_disk_uid(disk,uid);
if ( uiid != -1)
{
img = get(source, uiid, true);
}
}
else if (!(source = disk->vector_value("IMAGE_ID")).empty())
{
int iid = get_disk_id(source);
if ( iid != -1)
{
img = get(iid, true);
}
}
if ( img != 0 )
{
img->disk_attribute(disk, img_type, dev_prefix, inherit_image_attrs);
datastore_id = img->get_ds_id();
img->unlock();
ds = ds_pool->get(datastore_id, true);
if ( ds != 0 )
{
ds->disk_attribute(disk, inherit_datastore_attrs);
ds->unlock();
}
}
disk->replace("DISK_ID", disk_id);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImagePool::authorize_disk(VectorAttribute * disk,int uid, AuthRequest * ar)
{
string source;
Image * img = 0;
PoolObjectAuth perm;
if (!(source = disk->vector_value("IMAGE")).empty())

View File

@ -1725,8 +1725,8 @@ void LifeCycleManager::disk_snapshot_success(int vid)
int disk_id, ds_id, snap_id;
int img_id = -1;
Quotas::QuotaType qt;
Template *quotas = 0;
Template *ds_quotas = 0;
Template *vm_quotas = 0;
const VectorAttribute* disk;
Snapshots snaps(-1);
@ -1750,8 +1750,8 @@ void LifeCycleManager::disk_snapshot_success(int vid)
return;
}
int uid = vm->get_uid();
int gid = vm->get_gid();
int vm_uid = vm->get_uid();
int vm_gid = vm->get_gid();
VirtualMachine::LcmState state = vm->get_lcm_state();
@ -1773,7 +1773,7 @@ void LifeCycleManager::disk_snapshot_success(int vid)
case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF:
case VirtualMachine::DISK_SNAPSHOT_DELETE_SUSPENDED:
vm->log("LCM", Log::INFO, "VM disk snapshot deleted.");
vm->delete_disk_snapshot(disk_id, snap_id, qt, &quotas);
vm->delete_disk_snapshot(disk_id, snap_id, &ds_quotas, &vm_quotas);
break;
@ -1803,24 +1803,28 @@ void LifeCycleManager::disk_snapshot_success(int vid)
vm->unlock();
if ( quotas != 0 )
if ( ds_quotas != 0 )
{
if (qt == Quotas::DATASTORE)
Image* img = ipool->get(img_id, true);
if(img != 0)
{
Image* img = ipool->get(img_id, true);
int img_uid = img->get_uid();
int img_gid = img->get_gid();
if(img != 0)
{
uid = img->get_uid();
gid = img->get_gid();
img->unlock();
img->unlock();
}
Quotas::quota_del(Quotas::DATASTORE, img_uid, img_gid, ds_quotas);
}
Quotas::quota_del(qt, uid, gid, quotas);
delete ds_quotas;
}
delete quotas;
if ( vm_quotas != 0 )
{
Quotas::quota_del(Quotas::VM, vm_uid, vm_gid, vm_quotas);
delete vm_quotas;
}
if(img_id != -1 && is_persistent && has_snaps)
@ -1858,8 +1862,8 @@ void LifeCycleManager::disk_snapshot_failure(int vid)
int disk_id, ds_id, snap_id;
int img_id = -1;
Quotas::QuotaType qt;
Template *quotas = 0;
Template *ds_quotas = 0;
Template *vm_quotas = 0;
const VectorAttribute* disk;
Snapshots snaps(-1);
@ -1883,8 +1887,8 @@ void LifeCycleManager::disk_snapshot_failure(int vid)
return;
}
int uid = vm->get_uid();
int gid = vm->get_gid();
int vm_uid = vm->get_uid();
int vm_gid = vm->get_gid();
VirtualMachine::LcmState state = vm->get_lcm_state();
@ -1895,7 +1899,7 @@ void LifeCycleManager::disk_snapshot_failure(int vid)
case VirtualMachine::DISK_SNAPSHOT_POWEROFF:
case VirtualMachine::DISK_SNAPSHOT_SUSPENDED:
vm->log("LCM", Log::ERROR, "Could not take disk snapshot.");
vm->delete_disk_snapshot(disk_id, snap_id, qt, &quotas);
vm->delete_disk_snapshot(disk_id, snap_id, &ds_quotas, &vm_quotas);
break;
case VirtualMachine::DISK_SNAPSHOT_REVERT:
@ -1934,24 +1938,28 @@ void LifeCycleManager::disk_snapshot_failure(int vid)
vm->unlock();
if ( quotas != 0 )
if ( ds_quotas != 0 )
{
if (qt == Quotas::DATASTORE)
Image* img = ipool->get(img_id, true);
if(img != 0)
{
Image* img = ipool->get(img_id, true);
int img_uid = img->get_uid();
int img_gid = img->get_gid();
if(img != 0)
{
uid = img->get_uid();
gid = img->get_gid();
img->unlock();
img->unlock();
}
Quotas::quota_del(Quotas::DATASTORE, img_uid, img_gid, ds_quotas);
}
Quotas::quota_del(qt, uid, gid, quotas);
delete ds_quotas;
}
delete quotas;
if ( vm_quotas != 0 )
{
Quotas::quota_del(Quotas::VM, vm_uid, vm_gid, vm_quotas);
delete vm_quotas;
}
if(img_id != -1 && is_persistent && has_snaps)

View File

@ -84,7 +84,22 @@ public class Template extends PoolElement
*/
public static OneResponse info(Client client, int id)
{
return client.call(INFO, id);
return info(client, id, false);
}
/**
* Retrieves the information of the given Template.
*
* @param client XML-RPC Client.
* @param id The template id for the template to retrieve the information from
* @param extended optional flag to process the template and include
* extended information, such as the SIZE for each DISK
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int id, boolean extended)
{
return client.call(INFO, id, extended);
}
/**
@ -251,7 +266,20 @@ public class Template extends PoolElement
*/
public OneResponse info()
{
OneResponse response = info(client, id);
return info(false);
}
/**
* Retrieves the information of the given Template.
*
* @param extended optional flag to process the template and include
* extended information, such as the SIZE for each DISK
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public OneResponse info(boolean extended)
{
OneResponse response = info(client, id, extended);
super.processInfo(response);
return response;
}

View File

@ -157,7 +157,7 @@ public class GroupTest
res = system.getGroupQuotas();
assertTrue( res.getErrorMessage(), !res.isError() );
res = system.setGroupQuotas("VM = [ VMS = 7, MEMORY = 0, CPU = 3, VOLATILE_SIZE = 1 ]");
res = system.setGroupQuotas("VM = [ VMS = 7, MEMORY = 0, CPU = 3, SYSTEM_DISK_SIZE = 1 ]");
assertTrue( res.getErrorMessage(), !res.isError() );
Node node = system.getGroupQuotasXML();

View File

@ -173,7 +173,7 @@ public class UserTest
res = system.getUserQuotas();
assertTrue( res.getErrorMessage(), !res.isError() );
res = system.setUserQuotas("VM = [ VMS = 7, MEMORY = 0, CPU = 3, VOLATILE_SIZE = 1 ]");
res = system.setUserQuotas("VM = [ VMS = 7, MEMORY = 0, CPU = 3, SYSTEM_DISK_SIZE = 1 ]");
assertTrue( res.getErrorMessage(), !res.isError() );
Node node = system.getUserQuotasXML();

View File

@ -65,8 +65,22 @@ module OpenNebula
#######################################################################
# Retrieves the information of the given Template.
def info()
super(TEMPLATE_METHODS[:info], 'VMTEMPLATE')
# @param extended [true,false] optional flag to process the template and
# include extended information, such as the SIZE for each DISK
def info(extended=false)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(TEMPLATE_METHODS[:info], @pe_id, extended)
if !OpenNebula.is_error?(rc)
initialize_xml(rc, 'VMTEMPLATE')
rc = nil
@pe_id = self['ID'].to_i if self['ID']
@name = self['NAME'] if self['NAME']
end
return rc
end
alias_method :info!, :info

View File

@ -31,7 +31,7 @@ require 'nokogiri'
module OneDBFsck
VERSION = "4.11.80"
LOCAL_VERSION = "4.13.80"
LOCAL_VERSION = "4.13.85"
def check_db_version()
db_version = read_db_version()
@ -1642,7 +1642,7 @@ EOT
cpu_used = 0
mem_used = 0
vms_used = 0
vol_used = 0
sys_used = 0
# VNet quotas
vnet_usage = {}
@ -1671,10 +1671,34 @@ EOT
type = t_elem.text.upcase
}
size = 0
if !e.at_xpath("SIZE").nil?
size = e.at_xpath("SIZE").text.to_i
end
if ( type == "SWAP" || type == "FS")
e.xpath("SIZE").each { |size_elem|
vol_used += size_elem.text.to_i
}
sys_used += size
else
if !e.at_xpath("CLONE").nil?
clone = (e.at_xpath("CLONE").text.upcase == "YES")
target = nil
if clone
target = e.at_xpath("CLONE_TARGET").text if !e.at_xpath("CLONE_TARGET").nil?
else
target = e.at_xpath("LN_TARGET").text if !e.at_xpath("LN_TARGET").nil?
end
if !target.nil? && target != "NONE" # self or system
sys_used += size
if !e.at_xpath("DISK_SNAPSHOT_TOTAL_SIZE").nil?
sys_used += e.at_xpath("DISK_SNAPSHOT_TOTAL_SIZE").text.to_i
end
end
end
end
}
@ -1714,8 +1738,8 @@ EOT
vm_elem.add_child(doc.create_element("VMS")).content = "-1"
vm_elem.add_child(doc.create_element("VMS_USED")).content = "0"
vm_elem.add_child(doc.create_element("VOLATILE_SIZE")).content = "-1"
vm_elem.add_child(doc.create_element("VOLATILE_SIZE_USED")).content = "0"
vm_elem.add_child(doc.create_element("SYSTEM_DISK_SIZE")).content = "-1"
vm_elem.add_child(doc.create_element("SYSTEM_DISK_SIZE_USED")).content = "0"
end
@ -1754,10 +1778,10 @@ EOT
end
}
vm_elem.xpath("VOLATILE_SIZE_USED").each { |e|
if e.text != vol_used.to_s
log_error("#{resource} #{oid} quotas: VOLATILE_SIZE_USED has #{e.text} \tis\t#{vol_used}")
e.content = vol_used.to_s
vm_elem.xpath("SYSTEM_DISK_SIZE_USED").each { |e|
if e.text != sys_used.to_s
log_error("#{resource} #{oid} quotas: SYSTEM_DISK_SIZE_USED has #{e.text} \tis\t#{sys_used}")
e.content = sys_used.to_s
end
}

View File

@ -29,7 +29,7 @@ include OpenNebula
module OneDBImportSlave
VERSION = "4.11.80"
LOCAL_VERSION = "4.13.80"
LOCAL_VERSION = "4.13.85"
def check_db_version(master_db_version, slave_db_version)
if ( master_db_version[:version] != VERSION ||

View File

@ -0,0 +1,199 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
module Migrator
def db_version
"4.13.85"
end
def one_version
"OpenNebula 4.13.85"
end
def up
init_log_time()
# 1727
@db.run "ALTER TABLE user_quotas RENAME TO old_user_quotas;"
@db.run "CREATE TABLE user_quotas (user_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
@db.transaction do
# oneadmin does not have quotas
@db.fetch("SELECT * FROM old_user_quotas WHERE user_oid=0") do |row|
@db[:user_quotas].insert(row)
end
@db.fetch("SELECT * FROM old_user_quotas WHERE user_oid>0") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
calculate_quotas(doc, "uid=#{row[:user_oid]}", "User")
@db[:user_quotas].insert(
:user_oid => row[:user_oid],
:body => doc.root.to_s)
end
end
@db.run "DROP TABLE old_user_quotas;"
log_time()
@db.run "ALTER TABLE group_quotas RENAME TO old_group_quotas;"
@db.run "CREATE TABLE group_quotas (group_oid INTEGER PRIMARY KEY, body MEDIUMTEXT);"
@db.transaction do
# oneadmin does not have quotas
@db.fetch("SELECT * FROM old_group_quotas WHERE group_oid=0") do |row|
@db[:group_quotas].insert(row)
end
@db.fetch("SELECT * FROM old_group_quotas WHERE group_oid>0") do |row|
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
calculate_quotas(doc, "gid=#{row[:group_oid]}", "Group")
@db[:group_quotas].insert(
:group_oid => row[:group_oid],
:body => doc.root.to_s)
end
end
@db.run "DROP TABLE old_group_quotas;"
log_time()
default_user_quotas = nil
default_group_quotas = nil
@db.fetch("SELECT * FROM system_attributes WHERE name = 'DEFAULT_USER_QUOTAS'") do |row|
default_user_quotas = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
vm_elem = default_user_quotas.root.at_xpath("VM_QUOTA/VM")
if !vm_elem.nil?
vm_elem.at_xpath("VOLATILE_SIZE").name = "SYSTEM_DISK_SIZE"
vm_elem.at_xpath("VOLATILE_SIZE_USED").name = "SYSTEM_DISK_SIZE_USED"
end
end
@db.fetch("SELECT * FROM system_attributes WHERE name = 'DEFAULT_GROUP_QUOTAS'") do |row|
default_group_quotas = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
vm_elem = default_group_quotas.root.at_xpath("VM_QUOTA/VM")
if !vm_elem.nil?
vm_elem.at_xpath("VOLATILE_SIZE").name = "SYSTEM_DISK_SIZE"
vm_elem.at_xpath("VOLATILE_SIZE_USED").name = "SYSTEM_DISK_SIZE_USED"
end
end
if !default_user_quotas.nil?
@db[:system_attributes].where(:name => "DEFAULT_USER_QUOTAS").update(
:body => default_user_quotas.root.to_s)
end
if !default_group_quotas.nil?
@db[:system_attributes].where(:name => "DEFAULT_GROUP_QUOTAS").update(
:body => default_group_quotas.root.to_s)
end
log_time()
return true
end
# Copied from fsck file, this method only recalculates the SYSTEM_DISK quotas
def calculate_quotas(doc, where_filter, resource)
oid = doc.root.at_xpath("ID").text.to_i
sys_used = 0
@db.fetch("SELECT body FROM vm_pool WHERE #{where_filter} AND state<>6") do |vm_row|
vmdoc = Nokogiri::XML(vm_row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
vmdoc.root.xpath("TEMPLATE/DISK").each { |e|
type = ""
e.xpath("TYPE").each { |t_elem|
type = t_elem.text.upcase
}
size = 0
if !e.at_xpath("SIZE").nil?
size = e.at_xpath("SIZE").text.to_i
end
if ( type == "SWAP" || type == "FS")
sys_used += size
else
if !e.at_xpath("CLONE").nil?
clone = (e.at_xpath("CLONE").text.upcase == "YES")
target = nil
if clone
target = e.at_xpath("CLONE_TARGET").text if !e.at_xpath("CLONE_TARGET").nil?
else
target = e.at_xpath("LN_TARGET").text if !e.at_xpath("LN_TARGET").nil?
end
if !target.nil? && target != "NONE" # self or system
sys_used += size
if !e.at_xpath("DISK_SNAPSHOT_TOTAL_SIZE").nil?
sys_used += e.at_xpath("DISK_SNAPSHOT_TOTAL_SIZE").text.to_i
end
end
end
end
}
end
vm_elem = doc.root.at_xpath("VM_QUOTA/VM")
if !vm_elem.nil?
vm_elem.at_xpath("VOLATILE_SIZE").name = "SYSTEM_DISK_SIZE"
vm_elem.at_xpath("VOLATILE_SIZE_USED").name = "SYSTEM_DISK_SIZE_USED"
else
doc.root.xpath("VM_QUOTA").each { |e| e.remove }
vm_quota = doc.root.add_child(doc.create_element("VM_QUOTA"))
vm_elem = vm_quota.add_child(doc.create_element("VM"))
vm_elem.add_child(doc.create_element("CPU")).content = "-1"
vm_elem.add_child(doc.create_element("CPU_USED")).content = "0"
vm_elem.add_child(doc.create_element("MEMORY")).content = "-1"
vm_elem.add_child(doc.create_element("MEMORY_USED")).content = "0"
vm_elem.add_child(doc.create_element("VMS")).content = "-1"
vm_elem.add_child(doc.create_element("VMS_USED")).content = "0"
vm_elem.add_child(doc.create_element("SYSTEM_DISK_SIZE")).content = "-1"
vm_elem.add_child(doc.create_element("SYSTEM_DISK_SIZE_USED")).content = "0"
end
vm_elem.xpath("SYSTEM_DISK_SIZE_USED").each { |e|
if e.text != sys_used.to_s
#puts("#{resource} #{oid} quotas: SYSTEM_DISK_SIZE_USED has #{e.text} \tis\t#{sys_used}")
e.content = sys_used.to_s
end
}
end
end

View File

@ -26,7 +26,7 @@ require 'nokogiri'
module OneDBPatch
VERSION = "4.11.80"
LOCAL_VERSION = "4.13.80"
LOCAL_VERSION = "4.13.85"
def is_hot_patch(ops)
return true

View File

@ -114,7 +114,11 @@ bool VirtualMachineAllocate::allocate_authorization(
// -------------------------- Check Quotas ----------------------------
if ( quota_authorization(tmpl, Quotas::VIRTUALMACHINE, att) == false )
VirtualMachineTemplate aux_tmpl(*ttmpl);
VirtualMachine::disk_extended_info(att.uid, &aux_tmpl);
if ( quota_authorization(&aux_tmpl, Quotas::VIRTUALMACHINE, att) == false )
{
return false;
}

View File

@ -68,6 +68,99 @@ void RequestManagerInfo::request_execute(xmlrpc_c::paramList const& paramList,
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void TemplateInfo::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
VMTemplatePool * tpool = static_cast<VMTemplatePool *>(pool);
VirtualMachineTemplate * extended_tmpl = 0;
VMTemplate * vm_tmpl;
PoolObjectAuth perms;
int oid = xmlrpc_c::value_int(paramList.getInt(1));
bool extended = false;
string str;
if ( paramList.size() > 2 )
{
extended = xmlrpc_c::value_boolean(paramList.getBoolean(2));
}
vm_tmpl = tpool->get(oid,true);
if ( vm_tmpl == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(auth_object),oid),
att);
return;
}
if (extended)
{
extended_tmpl = vm_tmpl->clone_template();
}
vm_tmpl->get_permissions(perms);
vm_tmpl->unlock();
AuthRequest ar(att.uid, att.group_ids);
ar.add_auth(auth_op, perms); //USE TEMPLATE
if (extended)
{
VirtualMachine::disk_extended_info(att.uid, extended_tmpl);
}
if ( att.uid != UserPool::ONEADMIN_ID && att.gid != GroupPool::ONEADMIN_ID )
{
if (UserPool::authorize(ar) == -1)
{
failure_response(AUTHORIZATION,
authorization_error(ar.message, att),
att);
delete extended_tmpl;
return;
}
}
vm_tmpl = tpool->get(oid,true);
if ( vm_tmpl == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(auth_object),oid),
att);
delete extended_tmpl;
return;
}
if (extended)
{
vm_tmpl->to_xml(str, extended_tmpl);
delete extended_tmpl;
}
else
{
vm_tmpl->to_xml(str);
}
vm_tmpl->unlock();
success_response(str, att);
return;
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void VirtualNetworkInfo::to_xml(RequestAttributes& att, PoolObjectSQL * object,
string& str)
{

View File

@ -42,6 +42,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
VMTemplatePool * tpool = static_cast<VMTemplatePool *>(pool);
VirtualMachineTemplate * tmpl;
VirtualMachineTemplate * extended_tmpl = 0;
VirtualMachineTemplate uattrs;
VMTemplate * rtmpl;
@ -163,15 +164,18 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
if ( quota_authorization(tmpl, Quotas::VIRTUALMACHINE, att) == false )
extended_tmpl = new VirtualMachineTemplate(*tmpl);
VirtualMachine::disk_extended_info(att.uid, extended_tmpl);
if ( quota_authorization(extended_tmpl, Quotas::VIRTUALMACHINE, att) == false )
{
delete tmpl;
delete extended_tmpl;
return;
}
}
Template tmpl_back(*tmpl);
rc = vmpool->allocate(att.uid, att.gid, att.uname, att.gname, att.umask,
tmpl, &vid, error_str, on_hold);
@ -181,11 +185,18 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
allocate_error(PoolObjectSQL::VM,error_str),
att);
quota_rollback(&tmpl_back, Quotas::VIRTUALMACHINE, att);
if (extended_tmpl != 0)
{
quota_rollback(extended_tmpl, Quotas::VIRTUALMACHINE, att);
}
delete extended_tmpl;
return;
}
delete extended_tmpl;
success_response(vid, att);
}

View File

@ -1513,9 +1513,8 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
Nebula& nd = Nebula::instance();
DispatchManager * dm = nd.get_dm();
VirtualMachineTemplate * tmpl = new VirtualMachineTemplate();
VirtualMachineTemplate * deltas = 0;
PoolObjectAuth vm_perms;
VirtualMachineTemplate tmpl;
PoolObjectAuth vm_perms;
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
VirtualMachine * vm;
@ -1531,13 +1530,11 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
// Parse Disk template
// -------------------------------------------------------------------------
rc = tmpl->parse_str_or_xml(str_tmpl, error_str);
rc = tmpl.parse_str_or_xml(str_tmpl, error_str);
if ( rc != 0 )
{
failure_response(INTERNAL, error_str, att);
delete tmpl;
return;
}
@ -1545,9 +1542,8 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
// Authorize the operation & check quotas
// -------------------------------------------------------------------------
if ( vm_authorization(id, 0, tmpl, att, 0, 0, 0, auth_op) == false )
if ( vm_authorization(id, 0, &tmpl, att, 0, 0, 0, auth_op) == false )
{
delete tmpl;
return;
}
@ -1567,42 +1563,36 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes att_quota(vm_perms.uid, vm_perms.gid, att);
volatile_disk = VirtualMachine::is_volatile(tmpl);
volatile_disk = VirtualMachine::is_volatile(&tmpl);
if ( volatile_disk )
VirtualMachineTemplate deltas(tmpl);
VirtualMachine::disk_extended_info(att.uid, &deltas);
deltas.add("VMS", 0);
if (quota_resize_authorization(id, &deltas, att_quota) == false)
{
deltas = new VirtualMachineTemplate(*tmpl);
deltas->add("VMS", 0);
if (quota_resize_authorization(id, deltas, att_quota) == false)
{
delete tmpl;
delete deltas;
return;
}
return;
}
else
if (volatile_disk == false)
{
if ( quota_authorization(tmpl, Quotas::IMAGE, att_quota) == false )
if ( quota_authorization(&tmpl, Quotas::IMAGE, att_quota) == false )
{
delete tmpl;
quota_rollback(&deltas, Quotas::VM, att_quota);
return;
}
}
rc = dm->attach(id, tmpl, error_str);
rc = dm->attach(id, &tmpl, error_str);
if ( rc != 0 )
{
if ( volatile_disk )
quota_rollback(&deltas, Quotas::VM, att_quota);
if (volatile_disk == false)
{
quota_rollback(deltas, Quotas::VM, att_quota);
}
else
{
quota_rollback(tmpl, Quotas::IMAGE, att_quota);
quota_rollback(&tmpl, Quotas::IMAGE, att_quota);
}
failure_response(ACTION,
@ -1614,9 +1604,6 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
success_response(id, att);
}
delete tmpl;
delete deltas;
return;
}
@ -2356,7 +2343,9 @@ void VirtualMachineDiskSnapshotCreate::request_execute(
const VectorAttribute * disk;
VectorAttribute * delta_disk = 0;
Template deltas;
Template ds_deltas;
Template vm_deltas;
bool do_vm_quota;
int rc;
int snap_id;
@ -2366,9 +2355,8 @@ void VirtualMachineDiskSnapshotCreate::request_execute(
int did = xmlrpc_c::value_int(paramList.getInt(2));
string name = xmlrpc_c::value_string(paramList.getString(3));
// ------------------------------------------------------------------------
// Check quotas for the new snapshot
// Check request consistency (VM & disk exists, no volatile)
// ------------------------------------------------------------------------
if ((vm = get_vm(id, att)) == 0)
{
@ -2405,8 +2393,10 @@ void VirtualMachineDiskSnapshotCreate::request_execute(
return;
}
RequestAttributes att_quota;
RequestAttributes ds_att_quota;
RequestAttributes vm_att_quota;
//--------------------------- Persistent Images ----------------------------
if (persistent)
{
PoolObjectAuth img_perms;
@ -2431,35 +2421,44 @@ void VirtualMachineDiskSnapshotCreate::request_execute(
return;
}
att_quota = RequestAttributes(img_perms.uid, img_perms.gid, att);
ds_att_quota = RequestAttributes(img_perms.uid, img_perms.gid, att);
deltas.add("DATASTORE", ds_id);
deltas.add("SIZE", disk_size);
deltas.add("IMAGES", 0);
ds_deltas.add("DATASTORE", ds_id);
ds_deltas.add("SIZE", disk_size);
ds_deltas.add("IMAGES", 0);
if (!quota_authorization(&deltas, Quotas::DATASTORE, att_quota))
if (!quota_authorization(&ds_deltas, Quotas::DATASTORE, ds_att_quota))
{
return;
}
}
else
//--------------------- Account for System DS storage ----------------------
do_vm_quota = (VirtualMachine::disk_target(disk) != "NONE"); // self or system
if (do_vm_quota)
{
if ( vm_authorization(id, 0, 0, att, 0, 0, 0, auth_op) == false )
{
return;
}
att_quota = RequestAttributes(vm_perms.uid, vm_perms.gid, att);
vm_att_quota = RequestAttributes(vm_perms.uid, vm_perms.gid, att);
delta_disk = new VectorAttribute("DISK");
delta_disk->replace("TYPE", "FS");
delta_disk->replace("SIZE", disk_size);
deltas.add("VMS", 0);
deltas.set(delta_disk);
vm_deltas.add("VMS", 0);
vm_deltas.set(delta_disk);
if (!quota_resize_authorization(id, &deltas, att_quota))
if (!quota_resize_authorization(id, &vm_deltas, vm_att_quota))
{
if (persistent)
{
quota_rollback(&ds_deltas, Quotas::DATASTORE, ds_att_quota);
}
return;
}
}
@ -2473,11 +2472,12 @@ void VirtualMachineDiskSnapshotCreate::request_execute(
{
if (persistent)
{
quota_rollback(&deltas, Quotas::DATASTORE, att_quota);
quota_rollback(&ds_deltas, Quotas::DATASTORE, ds_att_quota);
}
else
if (do_vm_quota)
{
quota_rollback(&deltas, Quotas::VM, att_quota);
quota_rollback(&vm_deltas, Quotas::VM, vm_att_quota);
}
failure_response(ACTION, request_error(error_str, ""), att);

View File

@ -309,6 +309,7 @@ void VirtualMachineXML::init_storage_usage()
vector<Attribute*>::iterator it;
long long size;
long long snapshot_size;
string st;
int ds_id;
bool clone;
@ -331,6 +332,11 @@ void VirtualMachineXML::init_storage_usage()
continue;
}
if (disk->vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_size) == 0)
{
size += snapshot_size;
}
if (isVolatile(disk))
{
system_ds_usage += size;

View File

@ -46,7 +46,8 @@
# Excution environment for Sunstone
# dev, Instead of pulling the minified js all the files will be pulled (app/main.js)
# NOTE. src/sunstone/public must be symlinked to /usr/lib/one/sunstone/public
# Check the Building from Source guide in the docs, for details on how to run
# Sunstone in development
# prod, the minified js will be used (dist/main.js)
:env: 'prod'

View File

@ -23,6 +23,7 @@ tabs:
create_vm:
capacity_select: true
network_select: true
disk_resize: true
settings-tab:
panel_tabs:
user_info_tab: false

View File

@ -23,6 +23,7 @@ tabs:
create_vm:
capacity_select: true
network_select: true
disk_resize: true
settings-tab:
panel_tabs:
user_info_tab: false

View File

@ -61,6 +61,14 @@ module OpenNebulaJSON
end
end
def info(extended=false)
if extended
super(true)
else
super()
end
end
def update(params=Hash.new)
template_hash = parse_json(params, 'vmtemplate')
if template_hash['template_raw']

View File

@ -82,8 +82,8 @@ class SunstoneServer < CloudServer
############################################################################
#
############################################################################
def get_resource(kind, id)
resource = retrieve_resource(kind, id)
def get_resource(kind, id, extended=false)
resource = retrieve_resource(kind, id, extended)
if OpenNebula.is_error?(resource)
return [404, resource.to_json]
else
@ -428,7 +428,7 @@ class SunstoneServer < CloudServer
############################################################################
#
############################################################################
def retrieve_resource(kind, id)
def retrieve_resource(kind, id, extended=false)
resource = case kind
when "group" then GroupJSON.new_with_id(id, @client)
when "cluster" then ClusterJSON.new_with_id(id, @client)
@ -448,7 +448,7 @@ class SunstoneServer < CloudServer
return error
end
rc = resource.info
rc = extended ? resource.info(true) : resource.info
if OpenNebula.is_error?(rc)
return rc
else

View File

@ -234,6 +234,7 @@ define(function(require) {
var callback = params.success;
var callbackError = params.error;
var id = params.data.id;
var data = params.data;
var request = subresource ?
OpenNebulaHelper.request(resource, subresource, id) :
OpenNebulaHelper.request(resource, "show", id);
@ -246,6 +247,7 @@ define(function(require) {
url: url,
type: "GET",
dataType: "json",
data: data,
success: function(response) {
return callback ? callback(request, response) : null;
},

View File

@ -15,6 +15,8 @@ define(function(require) {
var Humanize = require('utils/humanize');
var QuotaLimits = require('utils/quotas/quota-limits');
var Graphs = require('utils/graphs');
var RangeSlider = require('utils/range-slider');
var DisksResize = require('utils/disks-resize');
var ProvisionQuotaWidget = require('./provision-tab/users/quota-widget');
@ -297,16 +299,16 @@ define(function(require) {
' '+
'<span class="memory_unit">'+memory_unit+'</span> '+
'<small style="color: #999; margin-right: 10px">'+Locale.tr("MEMORY")+'</small>'+
'<span class="cost_value">0.00</span> '+
'<small style="color: #999;">'+Locale.tr("COST")+' / ' + Locale.tr("HOUR") + '</small>'+
'<span class="provision_create_template_cost_div hidden">' +
'<span class="cost_value">0.00</span> '+
'<small style="color: #999;">'+Locale.tr("COST")+' / ' + Locale.tr("HOUR") + '</small>'+
'</span>'+
'</span>'+
'</h3>'+
'<br>'+
'</div>'+
'</div>'+
(Config.provision.create_vm.isEnabled("capacity_select") && (capacity.SUNSTONE_CAPACITY_SELECT != "NO") ?
'<br>'+
'<br>'+
'<div class="row">'+
'<div class="large-12 large-centered columns">'+
'<dl class="accordion" data-accordion="provision_accordion_'+provision_instance_type_accordion_id+'">'+
@ -660,7 +662,6 @@ define(function(require) {
'<br>'+
'</div>'+
'</div>'+
'<br>'+
'<div class="row">'+
'<div class="large-12 large-centered columns">'+
'<dl class="accordion provision_nic_accordion" data-accordion="provision_accordion_'+provision_nic_accordion_id+'">'+
@ -1039,6 +1040,7 @@ define(function(require) {
$(".provision_accordion_template .select_template").show();
$("#provision_create_vm .provision_capacity_selector").html("");
$("#provision_create_vm .provision_disk_selector").html("");
$("#provision_create_vm .provision_network_selector").html("");
$("#provision_create_vm .provision_custom_attributes_selector").html("")
@ -1428,6 +1430,7 @@ define(function(require) {
var create_vm_context = $("#provision_create_vm");
if ($(this).hasClass("selected")){
$(".provision_disk_selector", create_vm_context).html("");
$(".provision_network_selector", create_vm_context).html("");
$(".provision_capacity_selector", create_vm_context).html("");
@ -1459,6 +1462,13 @@ define(function(require) {
$(".provision_capacity_selector", create_vm_context),
template_json.VMTEMPLATE.TEMPLATE);
var disksContext = $(".provision_disk_selector", create_vm_context);
if (Config.provision.create_vm.isEnabled("disk_resize")) {
DisksResize.insert(template_json, disksContext);
} else {
disksContext.html("");
}
if (Config.provision.create_vm.isEnabled("network_select") && (template_json.VMTEMPLATE.TEMPLATE.SUNSTONE_NETWORK_SELECT != "NO")) {
generate_provision_network_accordion(
$(".provision_network_selector", create_vm_context));
@ -1515,6 +1525,8 @@ define(function(require) {
}
});
var disks = DisksResize.retrieve($(".provision_disk_selector", context));
var instance_type = $(".provision_instance_types_ul .selected", context);
if (!template_id) {
@ -1532,6 +1544,10 @@ define(function(require) {
extra_info.template.nic = nics;
}
if (disks.length > 0) {
extra_info.template.DISK = disks;
}
if (instance_type.length > 0) {
var instance_typa_data = instance_type.data("opennebula");
delete instance_typa_data.name;

View File

@ -128,7 +128,7 @@ define(function(require) {
return {
"VM" : {
"VOLATILE_SIZE": QuotaLimits.QUOTA_LIMIT_DEFAULT,
"SYSTEM_DISK_SIZE": QuotaLimits.QUOTA_LIMIT_DEFAULT,
"VMS": vms_limit,
"MEMORY": mem_limit,
"CPU": cpu_limit

View File

@ -90,15 +90,14 @@
</div>
</div>
<br>
<br>
<div class="row">
<div class="large-10 large-centered columns">
<div class="provision_capacity_selector"></div>
<br>
<div class="provision_disk_selector"></div>
<br>
<div class="provision_network_selector"></div>
<br>
<br>
<div class="provision_custom_attributes_selector"></div>
</div>
</div>

View File

@ -12,6 +12,7 @@ define(function(require) {
var Tips = require('utils/tips');
var UserInputs = require('utils/user-inputs');
var WizardFields = require('utils/wizard-fields');
var DisksResize = require('utils/disks-resize');
/*
CONSTANTS
@ -87,6 +88,10 @@ define(function(require) {
};
var tmp_json = WizardFields.retrieve($(".template_user_inputs" + template_id, context));
var disks = DisksResize.retrieve($(".disksContext" + template_id, context));
if (disks.length > 0) {
tmp_json.DISK = disks;
}
extra_info['template'] = tmp_json;
@ -128,17 +133,8 @@ define(function(require) {
$("#instantiate_vm_template_proceed", context).attr("disabled", "disabled");
var selected_nodes = Sunstone.getDataTable(TEMPLATES_TAB_ID).elements();
$("#instantiate_vm_user_inputs", context).html(
'<br>' +
'<div class="row">' +
'<div class="large-12 large-centered columns">' +
'<div class="subheader">' +
Locale.tr("Templates to be instantiated") +
'</div>' +
'<ul class="disc list_of_templates">' +
'</ul>' +
'</div>' +
'</div>');
var templatesContext = $(".list_of_templates", context)
templatesContext.html("");
$.each(selected_nodes, function(index, template_id) {
OpenNebulaTemplate.show({
@ -147,15 +143,24 @@ define(function(require) {
},
timeout: true,
success: function (request, template_json) {
$(".list_of_templates", context).append("<li>" + template_json.VMTEMPLATE.NAME + '</li>')
templatesContext.append(
'<h3 style="border-bottom: 1px solid #efefef; padding-bottom: 10px;">' +
'<span style="border-bottom: 2px solid #0098c3; padding: 0px 50px 10px 0px;">' +
template_json.VMTEMPLATE.NAME +
'</span>' +
'</h3>'+
'<div class="large-11 columns large-centered disksContext' + template_json.VMTEMPLATE.ID + '"></div>' +
'<div class="large-11 columns large-centered template_user_inputs' + template_json.VMTEMPLATE.ID + '"></div>'+
'<br>');
var inputs_div = $("<div class='template_user_inputs" + template_json.VMTEMPLATE.ID + "'></div>").appendTo(
$("#instantiate_vm_user_inputs", context));
DisksResize.insert(template_json, $(".disksContext" + template_json.VMTEMPLATE.ID, context));
var inputs_div = $(".template_user_inputs" + template_json.VMTEMPLATE.ID, context);
UserInputs.vmTemplateInsert(
inputs_div,
template_json,
{text_header: template_json.VMTEMPLATE.NAME});
{text_header: Locale.tr("Custom Attributes")});
inputs_div.data("opennebula_id", template_json.VMTEMPLATE.ID)
},

View File

@ -1,10 +1,12 @@
<div id="{{dialogId}}" class="reveal-modal" role="dialog" data-reveal >
<div id="{{dialogId}}" class="reveal-modal large" role="dialog" data-reveal >
<div class="row">
<h3 id="create_vnet_header" class="subheader">{{tr "Instantiate VM Template"}}</h3>
<div class="large-12 columns">
<h3 id="create_vnet_header" class="subheader">{{tr "Instantiate VM Template"}}</h3>
</div>
</div>
<form data-abide="ajax" id="{{dialogId}}Form" action="" class="custom creation">
<div class="row">
<div class="large-12 columns">
<div class="large-4 columns">
<label for="vm_name">
{{tr "VM Name"}}
<span class="tip">
@ -12,20 +14,17 @@
</span>
</label>
<input type="text" name="vm_name" id="vm_name" />
</div>
</div>
<div class="row">
<div class="large-12 columns">
</div>
<div class="large-4 columns">
<label for="vm_n_times">
{{tr "Number of instances"}}
<span class="tip">
{{tr "Number of Virtual Machines that will be created using this template"}}.
</span>
</label>
<input type="text" name="vm_n_times" id="vm_n_times" value="1"></div>
</div>
<div class="row">
<div class="large-12 columns">
<input type="text" name="vm_n_times" id="vm_n_times" value="1">
</div>
<div class="large-4 columns">
<input type="checkbox" name="hold" id="hold"/>
<label for="hold">
{{tr "Hold"}}
@ -35,7 +34,9 @@
</label>
</div>
</div>
<div id="instantiate_vm_user_inputs"> <i class="fa fa-spinner fa-spin"></i>
<div class="row">
<div class="large-11 large-centered columns list_of_templates">
</div>
</div>
<div class="form_buttons">
<button class="button radius right success" id="instantiate_vm_template_proceed" value="Template.instantiate_vms">{{tr "Instantiate"}}</button>

View File

@ -0,0 +1,132 @@
define(function(require){
var Locale = require('utils/locale');
var Config = require('sunstone-config');
var OpenNebula = require('opennebula');
var RangeSlider = require('utils/range-slider');
return {
'insert': _insert,
'retrieve': _retrieve
};
function _insert(template_json, disksContext) {
var template_disk = template_json.VMTEMPLATE.TEMPLATE.DISK
var disks = []
if ($.isArray(template_disk)) {
disks = template_disk
} else if (!$.isEmptyObject(template_disk)) {
disks = [template_disk]
}
if (disks.length > 0) {
disksContext.html(
'<div class="row">'+
'<div class="large-12 columns">'+
'<h3 class="subheader text-right">'+
'<span class="left">'+
'<i class="fa fa-tasks fa-lg"></i>&emsp;'+
Locale.tr("Disks")+
'</span>'+
'<span class="provision_create_template_disk_cost_div hidden">' +
'<span class="cost_value">0.00</span> '+
'<small style="color: #999;">'+Locale.tr("COST")+' / ' + Locale.tr("HOUR") + '</small>'+
'</span>'+
'</h3>'+
'</div>'+
'</div>'+
'<div class="row">'+
'<div class="large-12 large-centered columns disksContainer">'+
'<span class="text-center" style="font-size:80px">'+
'<i class="fa fa-spinner fa-spin"></i>'+
'</span>'+
'</div>'+
'</div>'+
'<br>')
OpenNebula.Template.show({
data : {
id: template_json.VMTEMPLATE.ID,
extended: true
},
success: function(request, extendedTemplateJSON) {
var extendedTemplateDisk = extendedTemplateJSON.VMTEMPLATE.TEMPLATE.DISK;
var extendedDisks = []
if ($.isArray(extendedTemplateDisk)) {
extendedDisks = extendedTemplateDisk
} else if (!$.isEmptyObject(extendedTemplateDisk)) {
extendedDisks = [extendedTemplateDisk]
}
var disk_cost = template_json.VMTEMPLATE.TEMPLATE.DISK_COST;
if (disk_cost && Config.isFeatureEnabled("showback")) {
$(".provision_create_template_disk_cost_div", disksContext).show();
disksContext.on("change.fndtn.slider", '.range-slider', function(){
/*if ($(this).attr('data-slider') <= 0) {
var diskContainer = $(this).parent('.diskContainer');
$("#SIZE", diskContainer).val(diskContainer.data('original_size'));
}*/
var cost = 0;
$('.range-slider', disksContext).each(function(){
if ($(this).attr('data-slider') > 0) {
cost += $(this).attr('data-slider') * disk_cost
}
})
$(".cost_value", disksContext).html(cost.toFixed(2));
});
} else {
$(".provision_create_template_disk_cost_div", disksContext).hide();
}
var diskContext;
$(".disksContainer", disksContext).html("");
$.each(extendedDisks, function(disk_id, disk) {
diskContext = $('<div class="row diskContainer">'+
'<div class="large-12 columns diskSlider">' +
'</div>' +
'</div>').appendTo($(".disksContainer", disksContext));
diskContext.data('template_disk', disks[disk_id]);
var sizeGB = disk.SIZE / 1024;
diskContext.data('original_size', sizeGB);
RangeSlider.insert({
'label': disk.IMAGE,
'unitLabel': 'GBs',
'name': 'SIZE',
'start': sizeGB,
'end': sizeGB + 500,
'step': 10,
'startValue': sizeGB
}, $(".diskSlider", diskContext))
})
}
})
} else {
disksContext.html("");
}
}
function _retrieve(context) {
var disks = [];
var disk, size;
$(".diskContainer", context).each(function(){
if ($(this).data("template_disk")) {
disk = $(this).data("template_disk");
original_size = $(this).data("original_size");
size = $("#SIZE", this).val();
if (size && size > original_size && size > 0) {
disk['SIZE'] = Math.ceil(size * 1024);
}
}
if (disk) {
disks.push(disk);
}
});
return disks;
}
});

View File

@ -6,7 +6,7 @@ define(function(require) {
"CPU": QUOTA_LIMIT_UNLIMITED,
"MEMORY": QUOTA_LIMIT_UNLIMITED,
"VMS": QUOTA_LIMIT_UNLIMITED,
"VOLATILE_SIZE": QUOTA_LIMIT_UNLIMITED,
"SYSTEM_DISK_SIZE": QUOTA_LIMIT_UNLIMITED,
}
},
"DATASTORE_QUOTA": {},
@ -20,7 +20,7 @@ define(function(require) {
"CPU": QUOTA_LIMIT_UNLIMITED,
"MEMORY": QUOTA_LIMIT_UNLIMITED,
"VMS": QUOTA_LIMIT_UNLIMITED,
"VOLATILE_SIZE": QUOTA_LIMIT_UNLIMITED,
"SYSTEM_DISK_SIZE": QUOTA_LIMIT_UNLIMITED,
}
},
"DATASTORE_QUOTA": {},
@ -74,7 +74,7 @@ define(function(require) {
"VMS" : QUOTA_LIMIT_UNLIMITED,
"MEMORY" : QUOTA_LIMIT_UNLIMITED,
"CPU" : QUOTA_LIMIT_UNLIMITED,
"VOLATILE_SIZE" : QUOTA_LIMIT_UNLIMITED
"SYSTEM_DISK_SIZE" : QUOTA_LIMIT_UNLIMITED
}
};
}

View File

@ -38,8 +38,8 @@ define(function(require) {
CPU_USED : 0,
MEMORY : QUOTA_LIMIT_DEFAULT,
MEMORY_USED : 0,
VOLATILE_SIZE : QUOTA_LIMIT_DEFAULT,
VOLATILE_SIZE_USED : 0
SYSTEM_DISK_SIZE : QUOTA_LIMIT_DEFAULT,
SYSTEM_DISK_SIZE_USED : 0
}
};
}
@ -186,12 +186,12 @@ define(function(require) {
}
/**
* Returns a widget with the volatile disk quotas
* Returns a widget with the system disk quotas
* @param {Object} info User/Group object
* @param {Object} default_quotas default quotas for Users/Groups
* @return {string} html string
*/
function _volatileWidget(info, default_quotas){
function _systemDiskWidget(info, default_quotas){
var empty_quotas = $.isEmptyObject(info.VM_QUOTA);
var quotas_tab_html = "";
@ -204,29 +204,29 @@ define(function(require) {
'<fieldset>';
}
var volatile_bar;
var system_bar;
if (!empty_quotas){
volatile_bar = _editableQuotaBar(
info.VM_QUOTA.VM.VOLATILE_SIZE_USED,
info.VM_QUOTA.VM.VOLATILE_SIZE,
default_quotas.VM_QUOTA.VM.VOLATILE_SIZE,
system_bar = _editableQuotaBar(
info.VM_QUOTA.VM.SYSTEM_DISK_SIZE_USED,
info.VM_QUOTA.VM.SYSTEM_DISK_SIZE,
default_quotas.VM_QUOTA.VM.SYSTEM_DISK_SIZE,
{ mb: true,
quota_name: "VM_VOLATILE_SIZE"
quota_name: "VM_SYSTEM_DISK_SIZE"
});
} else {
volatile_bar = _editableQuotaBar(
system_bar = _editableQuotaBar(
0,
QUOTA_LIMIT_DEFAULT,
default_quotas.VM_QUOTA.VM.VOLATILE_SIZE,
default_quotas.VM_QUOTA.VM.SYSTEM_DISK_SIZE,
{ mb: true,
quota_name: "VM_VOLATILE_SIZE"
quota_name: "VM_SYSTEM_DISK_SIZE"
});
}
quotas_tab_html +=
'<legend>' + Locale.tr("Volatile disks") + '</legend>\
<div>'+volatile_bar+'</div>\
'<legend>' + Locale.tr("System disks") + '</legend>\
<div>'+system_bar+'</div>\
<br>\
</fieldset>'
@ -696,7 +696,7 @@ define(function(require) {
var vms_quota = _vmsWidget(resource_info, default_quotas);
var cpu_quota = _cpuWidget(resource_info, default_quotas);
var memory_quota = _memoryWidget(resource_info, default_quotas);
var volatile_size_quota = _volatileWidget(resource_info, default_quotas);
var system_disk_size_quota = _systemDiskWidget(resource_info, default_quotas);
var image_quota = _imageWidget(resource_info, default_quotas);
var network_quota = _networkWidget(resource_info, default_quotas);
@ -750,7 +750,7 @@ define(function(require) {
</div>\
<div class="row">\
<div class="large-6 columns">' + memory_quota + '</div>\
<div class="large-6 columns">' + volatile_size_quota+ '</div>\
<div class="large-6 columns">' + system_disk_size_quota+ '</div>\
</div>\
<br><br>\
<div class="row">\
@ -855,7 +855,7 @@ define(function(require) {
"CPU" : input_val( $("div[quota_name=VM_CPU] input", parent_container) ),
"MEMORY" : input_val( $("div[quota_name=VM_MEMORY] input", parent_container) ),
"VMS" : input_val( $("div[quota_name=VM_VMS] input", parent_container) ),
"VOLATILE_SIZE" : input_val( $("div[quota_name=VM_VOLATILE_SIZE] input", parent_container) )
"SYSTEM_DISK_SIZE" : input_val( $("div[quota_name=VM_SYSTEM_DISK_SIZE] input", parent_container) )
};
$.each($("tr.image_quota_tr", parent_container), function(){
@ -1184,7 +1184,7 @@ define(function(require) {
var vms_quota = _vmsWidget(resource_info, default_quotas);
var cpu_quota = _cpuWidget(resource_info, default_quotas);
var memory_quota = _memoryWidget(resource_info, default_quotas);
var volatile_size_quota = _volatileWidget(resource_info, default_quotas);
var system_disk_size_quota = _systemDiskWidget(resource_info, default_quotas);
var image_quota = _imageWidget(resource_info, default_quotas);
var network_quota = _networkWidget(resource_info, default_quotas);
@ -1194,7 +1194,7 @@ define(function(require) {
'<div class="large-6 columns">' + vms_quota + '</div>\
<div class="large-6 columns">' + cpu_quota + '</div>\
<div class="large-6 columns">' + memory_quota + '</div>\
<div class="large-6 columns">' + volatile_size_quota+ '</div>');
<div class="large-6 columns">' + system_disk_size_quota+ '</div>');
$("#datastore_quota", context).html(
'<div class="large-12 columns">' + datastore_quota + '</div>');

View File

@ -0,0 +1,50 @@
define(function(require) {
var TemplateHTML = require('hbs!./range-slider/html');
return {
'insert': _insert
}
/*
Insert a range slider
@param {Object} opts Options for the slider
opts.label Label for the input
opts.tip String with the despription
opts.name Name of the input, it will be used for the wizard_field value
and the ID of the input
opts.start Start value of the slider
opts.end End value of the slider
opts.step Step value of the slider
opts.startValue Initialize the slider with this value
@param {Object} context div to insert the range slider
@returns {String} HTML row
*/
function _insert(opts, context) {
console.log(opts)
context.html(TemplateHTML(opts));
context.foundation('slider', 'reflow');
// Define the cpu slider
var input = $("#" + opts.name, context);
var slider = $("#" + opts.name + "Slider", context)
slider.on('change.fndtn.slider', function(){
if ($(this).attr('data-slider') >= 0) {
input.val($(this).attr('data-slider'));
}
});
input.on('change', function() {
if (this.value && this.value >= 0) {
slider.foundation('slider', 'set_value', this.value);
} else {
slider.foundation('slider', 'set_value', -1);
}
});
if (opts.startValue) {
slider.foundation('slider', 'set_value', opts.startValue);
input.val(opts.startValue);
}
}
});

View File

@ -0,0 +1,24 @@
<label class="" for="{{name}}">
{{label}}
{{#if tip}}
{{{tip tip}}}
{{/if}}
</label>
<div class="large-10 columns">
<div id="{{name}}Slider" class="range-slider radius" data-slider data-options="start: {{start}}; end: {{end}}; step: {{step}};">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden"></div>
</div>
<div class="large-2 columns">
{{#if unitLabel}}
<div class="small-9 columns">
<input type="text" id="{{name}}" name="{{name}}"/>
</div>
<div class="small-3 columns">
<span style="font-size: 18px; color: #999;">{{unitLabel}}</span>
</div>
{{else}}
<input type="text" wizard_field="{{name}}" id="{{name}}" name="{{name}}"/>
{{/if}}
</div>

View File

@ -19,13 +19,13 @@
COPYRIGHT_HOLDER="2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs"
PACKAGE_NAME="OpenNebula"
find ../public/app -name \*.js > file_list.txt
find ../app -name \*.js > file_list.txt
xgettext --from-code=utf-8 --copyright-holder="$COPYRIGHT_HOLDER" --package-name="$PACKAGE_NAME" --no-wrap --keyword= --keyword=tr -L JavaScript -f file_list.txt -p .
# xgettext-template project: https://github.com/gmarty/xgettext
# tail removes the first configuration lines for msgid ""
find ../public/app -name \*.hbs -exec sh -c "xgettext-template -L Handlebars --from-code utf-8 --force-po --keyword tr {}| tail -n +3 >> messages.po" \;
find ../app -name \*.hbs -exec sh -c "xgettext-template -L Handlebars --from-code utf-8 --force-po --keyword tr {}| tail -n +3 >> messages.po" \;
mv messages.po messages.pot
@ -35,4 +35,4 @@ msguniq messages.pot -o messages.pot --no-wrap
rm file_list.txt
# TODO hbs tr helper as a parameter to other helpers:
# {{#advancedSection (tr "Advanced Options") }}
# {{#advancedSection (tr "Advanced Options") }}

File diff suppressed because it is too large Load Diff

View File

@ -1304,3 +1304,11 @@ hr {
.tree ul:last-child li:last-child:after{
height:1em;
}
.diskSlider {
label {
font-size: 24px;
color: #777;
padding: 0 0.5rem;
}
}

View File

@ -546,7 +546,11 @@ get '/:resource/:id/template' do
end
get '/:resource/:id' do
@SunstoneServer.get_resource(params[:resource], params[:id])
if params[:extended]
@SunstoneServer.get_resource(params[:resource], params[:id], true)
else
@SunstoneServer.get_resource(params[:resource], params[:id])
end
end
##############################################################################

View File

@ -38,6 +38,8 @@ fi
. $TMCOMMON
DRIVER_PATH=$(dirname $0)
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
@ -52,6 +54,26 @@ SRC_DS_PATH="$(dirname $(dirname $SRC_ARG_PATH))"
SRC_PATH="${DST_DS_PATH}${SRC_ARG_PATH##$SRC_DS_PATH}"
#-------------------------------------------------------------------------------
# Get Image information
#-------------------------------------------------------------------------------
DISK_ID=$(basename ${DST_PATH} | cut -d. -f2)
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <(onevm show -x $VMID| $XPATH \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SIZE \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/ORIGINAL_SIZE)
SIZE="${XPATH_ELEMENTS[j++]}"
ORIGINAL_SIZE="${XPATH_ELEMENTS[j++]}"
ssh_make_path $DST_HOST $DST_DIR
#-------------------------------------------------------------------------------
@ -68,7 +90,15 @@ http://*)
*)
log "Cloning $SRC_PATH in $DST"
CLONE_CMD="cd $DST_DIR; rm -f $DST_PATH; $QEMU_IMG create -b $SRC_PATH -f qcow2 $DST_PATH"
ORIGINAL_SIZE=${ORIGINAL_SIZE:-0}
if [ "$SIZE" -ge "$ORIGINAL_SIZE" ]; then
RESIZE_CMD="; qemu-img resize ${DST_PATH} ${SIZE}M"
fi
CLONE_CMD="cd $DST_DIR; \
rm -f $DST_PATH; $QEMU_IMG create -b $SRC_PATH -f qcow2 $DST_PATH \
${RESIZE_CMD}"
ssh_exec_and_log "$DST_HOST" "$CLONE_CMD" "Error copying $SRC to $DST"
;;
esac

View File

@ -38,6 +38,8 @@ fi
. $TMCOMMON
DRIVER_PATH=$(dirname $0)
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
@ -52,6 +54,26 @@ SRC_DS_PATH="$(dirname $(dirname $SRC_ARG_PATH))"
SRC_PATH="${DST_DS_PATH}${SRC_ARG_PATH##$SRC_DS_PATH}"
#-------------------------------------------------------------------------------
# Get Image information
#-------------------------------------------------------------------------------
DISK_ID=$(basename ${DST_PATH} | cut -d. -f2)
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <(onevm show -x $VMID| $XPATH \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SIZE \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/ORIGINAL_SIZE)
SIZE="${XPATH_ELEMENTS[j++]}"
ORIGINAL_SIZE="${XPATH_ELEMENTS[j++]}"
#-------------------------------------------------------------------------------
# Create DST path
#-------------------------------------------------------------------------------
@ -72,8 +94,19 @@ http://*)
*)
log "Cloning $SRC_PATH in $DST"
ORIGINAL_SIZE=${ORIGINAL_SIZE:-0}
if [ "$SIZE" -ge "$ORIGINAL_SIZE" ]; then
RESIZE_CMD="; qemu-img resize ${DST_PATH} ${SIZE}M"
fi
CLONE_CMD="cd ${DST_DIR}; \
cp ${SRC_PATH} ${DST_PATH} \
${RESIZE_CMD}"
ssh_exec_and_log $DST_HOST \
"cd $DST_DIR; cp $SRC_PATH $DST_PATH" \
"$CLONE_CMD" \
"Error copying $SRC to $DST"
;;
esac

View File

@ -38,6 +38,8 @@ fi
. $TMCOMMON
DRIVER_PATH=$(dirname $0)
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
@ -53,6 +55,25 @@ DST_DIR=`dirname $DST_PATH`
ssh_make_path $DST_HOST $DST_DIR
#-------------------------------------------------------------------------------
# Get Image information
#-------------------------------------------------------------------------------
DISK_ID=$(basename ${DST_PATH} | cut -d. -f2)
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <(onevm show -x $VMID| $XPATH \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SIZE \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/ORIGINAL_SIZE)
SIZE="${XPATH_ELEMENTS[j++]}"
ORIGINAL_SIZE="${XPATH_ELEMENTS[j++]}"
#-------------------------------------------------------------------------------
# Copy files to the remote host
#-------------------------------------------------------------------------------
@ -71,6 +92,14 @@ http://*)
exec_and_log "$SCP -r ${SRC_PATH_SNAP} ${DST_PATH_SNAP}" \
"Error copying $SRC to $DST"
fi
ORIGINAL_SIZE=${ORIGINAL_SIZE:-0}
if [ "$SIZE" -ge "$ORIGINAL_SIZE" ]; then
RESIZE_CMD="qemu-img resize ${DST_PATH} ${SIZE}M"
ssh_exec_and_log "$DST_HOST" "$RESIZE_CMD" \
"Error resizing image $DST"
fi
;;
esac

View File

@ -22,7 +22,7 @@
/* -------------------------------------------------------------------------- */
const char * QuotaVirtualMachine::VM_METRICS[] =
{"VMS", "CPU", "MEMORY", "VOLATILE_SIZE"};
{"VMS", "CPU", "MEMORY", "SYSTEM_DISK_SIZE"};
const int QuotaVirtualMachine::NUM_VM_METRICS = 4;
@ -73,12 +73,12 @@ bool QuotaVirtualMachine::check(Template * tmpl,
return false;
}
size = VirtualMachine::get_volatile_disk_size(tmpl);
size = VirtualMachine::get_system_disk_size(tmpl);
vm_request.insert(make_pair("VMS",1));
vm_request.insert(make_pair("MEMORY", memory));
vm_request.insert(make_pair("CPU", cpu));
vm_request.insert(make_pair("VOLATILE_SIZE", size));
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", size));
return check_quota("", vm_request, default_quotas, error);
}
@ -109,12 +109,12 @@ void QuotaVirtualMachine::del(Template * tmpl)
vms = 1;
}
size = VirtualMachine::get_volatile_disk_size(tmpl);
size = VirtualMachine::get_system_disk_size(tmpl);
vm_request.insert(make_pair("VMS", vms));
vm_request.insert(make_pair("MEMORY", memory));
vm_request.insert(make_pair("CPU", cpu));
vm_request.insert(make_pair("VOLATILE_SIZE", size));
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", size));
del_quota("", vm_request);
}
@ -153,11 +153,11 @@ bool QuotaVirtualMachine::update(Template * tmpl,
vm_request.insert(make_pair("CPU", delta_cpu));
}
delta_size = VirtualMachine::get_volatile_disk_size(tmpl);
delta_size = VirtualMachine::get_system_disk_size(tmpl);
if ( delta_size != 0 )
{
vm_request.insert(make_pair("VOLATILE_SIZE", delta_size));
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", delta_size));
}
return check_quota("", vm_request, default_quotas, error);

View File

@ -122,7 +122,7 @@ void Snapshots::init()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Snapshots::create_snapshot(const string& name, unsigned int size_mb)
int Snapshots::create_snapshot(const string& name, long long size_mb)
{
VectorAttribute * snapshot = new VectorAttribute("SNAPSHOT");
@ -285,9 +285,9 @@ string Snapshots::get_snapshot_attribute(int id, const char * name) const
/* -------------------------------------------------------------------------- */
unsigned int Snapshots::get_snapshot_size(int id) const
long long Snapshots::get_snapshot_size(int id) const
{
unsigned int snap_size = 0;
long long snap_size = 0;
const VectorAttribute * snapshot = get_snapshot(id);
@ -338,10 +338,10 @@ bool Snapshots::test_delete(int id, string& error) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
unsigned int Snapshots::get_total_size() const
long long Snapshots::get_total_size() const
{
map<int, VectorAttribute *>::const_iterator it;
unsigned int size_mb, total_mb = 0;
long long size_mb, total_mb = 0;
for ( it = snapshot_pool.begin(); it != snapshot_pool.end(); it++)
{

View File

@ -1841,7 +1841,7 @@ int VirtualMachine::get_disk_images(string& error_str)
disk = static_cast<VectorAttribute * >(disks[i]);
rc = ipool->disk_attribute(oid,
rc = ipool->acquire_disk( oid,
disk,
i,
img_type,
@ -2092,7 +2092,7 @@ VectorAttribute * VirtualMachine::set_up_attach_disk(
// Acquire the new disk image
// -------------------------------------------------------------------------
int rc = ipool->disk_attribute(vm_id,
int rc = ipool->acquire_disk( vm_id,
new_disk,
max_disk_id + 1,
img_type,
@ -2317,9 +2317,10 @@ bool VirtualMachine::is_imported() const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
long long VirtualMachine::get_volatile_disk_size(Template * tmpl)
long long VirtualMachine::get_system_disk_size(Template * tmpl)
{
long long disk_size, size = 0;
long long size = 0;
long long disk_size, snapshot_size;
vector<const Attribute*> disks;
const VectorAttribute * disk;
@ -2335,21 +2336,24 @@ long long VirtualMachine::get_volatile_disk_size(Template * tmpl)
continue;
}
if (is_volatile(disk))
if (disk->vector_value("SIZE", disk_size) != 0)
{
if (disk->vector_value("SIZE", disk_size) == 0)
{
size += disk_size;
}
}
else if (!is_persistent(disk))
{
if (disk->vector_value("DISK_SNAPSHOT_TOTAL_SIZE", disk_size) == 0)
{
size += disk_size;
}
continue;
}
if (is_volatile(disk))
{
size += disk_size;
}
else if ( disk_target(disk) != "NONE") // self or system
{
size += disk_size;
if (disk->vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_size) == 0)
{
size += snapshot_size;
}
}
}
return size;
@ -2358,6 +2362,31 @@ long long VirtualMachine::get_volatile_disk_size(Template * tmpl)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string VirtualMachine::disk_target(const VectorAttribute * disk)
{
bool clone;
string target;
if (disk->vector_value("CLONE", clone) != 0)
{
return "";
}
if (clone)
{
target = disk->vector_value("CLONE_TARGET");
}
else
{
target = disk->vector_value("LN_TARGET");
}
return one_util::toupper(target);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VectorAttribute * VirtualMachine::get_attach_nic_info(
VirtualMachineTemplate * tmpl,
int& max_nic_id,
@ -3468,7 +3497,6 @@ int VirtualMachine::get_saveas_disk(int& disk_id, string& source,
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -3541,6 +3569,32 @@ void VirtualMachine::set_auth_request(int uid,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::disk_extended_info(int uid,
VirtualMachineTemplate *tmpl)
{
int num;
vector<Attribute * > disks;
VectorAttribute * disk;
ImagePool * ipool = Nebula::instance().get_ipool();
num = tmpl->get("DISK",disks);
for(int i=0; i<num; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
if ( disk == 0 )
{
continue;
}
ipool->disk_attribute(disk, i, uid);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
pthread_mutex_t VirtualMachine::lex_mutex = PTHREAD_MUTEX_INITIALIZER;
extern "C"
@ -4220,7 +4274,7 @@ int VirtualMachine::get_snapshot_disk(int& ds_id, string& tm_mad,
int VirtualMachine::new_disk_snapshot(int did, const string& name, string& error)
{
map<int, Snapshots *>::iterator it;
unsigned int size_mb, snap_size;
long long size_mb, snap_size;
int snap_id;
VectorAttribute * disk;
@ -4331,15 +4385,16 @@ int VirtualMachine::revert_disk_snapshot(int did, int snap_id)
/* -------------------------------------------------------------------------- */
void VirtualMachine::delete_disk_snapshot(int did, int snap_id,
Quotas::QuotaType& type, Template **quotas)
Template **ds_quotas, Template **vm_quotas)
{
map<int, Snapshots *>::iterator it;
unsigned int snap_size;
long long snap_size;
VectorAttribute * delta_disk;
VectorAttribute * disk = get_disk(did);
*quotas = 0;
*ds_quotas = 0;
*vm_quotas = 0;
if ( disk == 0 )
{
@ -4353,7 +4408,7 @@ void VirtualMachine::delete_disk_snapshot(int did, int snap_id,
return;
}
unsigned int ssize = it->second->get_snapshot_size(snap_id);
long long ssize = it->second->get_snapshot_size(snap_id);
it->second->delete_snapshot(snap_id);
@ -4372,26 +4427,23 @@ void VirtualMachine::delete_disk_snapshot(int did, int snap_id,
if ( is_persistent(disk) )
{
*quotas = new Template();
*ds_quotas = new Template();
(*quotas)->add("DATASTORE", disk->vector_value("DATASTORE_ID"));
(*quotas)->add("SIZE", (long long) ssize);
(*quotas)->add("IMAGES",0 );
type = Quotas::DATASTORE;
(*ds_quotas)->add("DATASTORE", disk->vector_value("DATASTORE_ID"));
(*ds_quotas)->add("SIZE", ssize);
(*ds_quotas)->add("IMAGES",0 );
}
else
if (disk_target(disk) != "NONE") // self or system
{
*quotas = new Template();
*vm_quotas = new Template();
delta_disk = new VectorAttribute("DISK");
delta_disk->replace("TYPE", "FS");
delta_disk->replace("SIZE", ssize);
(*quotas)->add("VMS", 0);
(*quotas)->set(delta_disk);
type = Quotas::VM;
(*vm_quotas)->add("VMS", 0);
(*vm_quotas)->set(delta_disk);
}
}

View File

@ -172,6 +172,14 @@ error_common:
/* ************************************************************************ */
string& VMTemplate::to_xml(string& xml) const
{
return to_xml(xml, obj_template);
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
string& VMTemplate::to_xml(string& xml, const Template* tmpl) const
{
ostringstream oss;
string template_xml;
@ -186,7 +194,7 @@ string& VMTemplate::to_xml(string& xml) const
<< "<NAME>" << name << "</NAME>"
<< perms_to_xml(perm_str)
<< "<REGTIME>" << regtime << "</REGTIME>"
<< obj_template->to_xml(template_xml)
<< tmpl->to_xml(template_xml)
<< "</VMTEMPLATE>";
xml = oss.str();