mirror of
https://github.com/OpenNebula/one.git
synced 2025-02-26 09:57:23 +03:00
F #4393: Moved Saveas implementation to VirtualMachineDiks. Fix bugs
This commit is contained in:
parent
033f8853da
commit
178489ef11
@ -982,28 +982,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
// Template
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
* Parse a string and substitute variables (e.g. $NAME) using the VM
|
||||
* template values:
|
||||
* @param attribute, the string to be parsed
|
||||
* @param parsed, the resulting parsed string
|
||||
* @param error description in case of failure
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int parse_template_attribute(const string& attribute,
|
||||
string& parsed,
|
||||
string& error);
|
||||
/**
|
||||
* Parse a file string variable (i.e. $FILE) using the FILE_DS datastores.
|
||||
* It should be used for OS/DS_KERNEL, OS/DS_INITRD, CONTEXT/DS_FILES.
|
||||
* @param attribute the string to be parsed
|
||||
* @param img_ids ids of the FILE images in the attribute
|
||||
* @param error description in case of failure
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int parse_file_attribute(string attribute,
|
||||
vector<int>& img_ids,
|
||||
string& error);
|
||||
/**
|
||||
* Updates the configuration attributes based on a template, the state of
|
||||
* the virtual machine is checked to assure operation consistency
|
||||
@ -1378,7 +1356,11 @@ public:
|
||||
* @param err_str describing the error if any
|
||||
* @return -1 if the image cannot saveas, 0 on success
|
||||
*/
|
||||
int set_saveas_disk(int disk_id, int snap_id, int &img_id, long long &size, string& err_str);
|
||||
int set_saveas_disk(int disk_id, int snap_id, int &img_id, long long &size,
|
||||
string& err_str)
|
||||
{
|
||||
return disks.set_saveas(disk_id, snap_id, img_id, size, err_str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set save attributes for the disk
|
||||
@ -1386,7 +1368,16 @@ public:
|
||||
* @param source to save the disk
|
||||
* @param img_id ID of the image this disk will be saved to
|
||||
*/
|
||||
int set_saveas_disk(int disk_id, const string& source, int img_id);
|
||||
int set_saveas_disk(int disk_id, const string& source, int img_id)
|
||||
{
|
||||
if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED
|
||||
&& lcm_state != HOTPLUG_SAVEAS_POWEROFF )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return disks.set_saveas(disk_id, source, img_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the corresponding state to save the disk.
|
||||
@ -1405,7 +1396,10 @@ public:
|
||||
* @return the ID of the image this disk will be saved to or -1 if it
|
||||
* is not found.
|
||||
*/
|
||||
int clear_saveas_disk();
|
||||
int clear_saveas_disk()
|
||||
{
|
||||
return disks.clear_saveas();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the original image id of the disk. It also checks that the disk can
|
||||
@ -1418,7 +1412,11 @@ public:
|
||||
* @return -1 if failure
|
||||
*/
|
||||
int get_saveas_disk(int& disk_id, string& source, int& image_id,
|
||||
string& snap_id, string& tm_mad, string& ds_id);
|
||||
string& snap_id, string& tm_mad, string& ds_id)
|
||||
{
|
||||
return disks.get_saveas_info(disk_id, source, image_id, snap_id,
|
||||
tm_mad, ds_id);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Authorization related functions
|
||||
@ -1473,7 +1471,10 @@ public:
|
||||
*/
|
||||
VirtualMachineDisk * delete_attach_disk()
|
||||
{
|
||||
return disks.delete_attach();
|
||||
VirtualMachineDisk * disk = disks.delete_attach();
|
||||
obj_template->remove(disk->vector_attribute());
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1514,6 +1515,19 @@ public:
|
||||
*/
|
||||
int set_resize_disk(int disk_id);
|
||||
|
||||
/**
|
||||
* Prepares a disk to be resized.
|
||||
* @param disk_id of disk
|
||||
* @param size new size for the disk (needs to be greater than current)
|
||||
* @param error
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int set_up_resize_disk(int disk_id, long size, string& error)
|
||||
{
|
||||
return disks.set_up_resize(disk_id, size, error);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// NIC Hotplug related functions
|
||||
// ------------------------------------------------------------------------
|
||||
@ -1860,11 +1874,9 @@ private:
|
||||
*/
|
||||
Log * _log;
|
||||
|
||||
|
||||
// *************************************************************************
|
||||
// DataBase implementation (Private)
|
||||
// *************************************************************************
|
||||
|
||||
/**
|
||||
* Bootstraps the database table(s) associated to the VirtualMachine
|
||||
* @return 0 on success
|
||||
@ -1943,15 +1955,64 @@ private:
|
||||
*/
|
||||
int update_monitoring(SqlDB * db);
|
||||
|
||||
/**
|
||||
* Function that renders the VM in XML format optinally including
|
||||
* extended information (all history records)
|
||||
* @param xml the resulting XML string
|
||||
* @param n_history Number of history records to include:
|
||||
* 0: none
|
||||
* 1: the last one
|
||||
* 2: all
|
||||
* @return a reference to the generated string
|
||||
*/
|
||||
string& to_xml_extended(string& xml, int n_history) const;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Attribute Parser
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Mutex to perform just one attribute parse at a time
|
||||
*/
|
||||
static pthread_mutex_t lex_mutex;
|
||||
|
||||
/**
|
||||
* Attributes not allowed in NIC_DEFAULT to avoid authorization bypass and
|
||||
* inconsistencies for NIC_DEFAULTS
|
||||
*/
|
||||
static const char* NO_NIC_DEFAULTS[];
|
||||
static const int NUM_NO_NIC_DEFAULTS;
|
||||
|
||||
/**
|
||||
* Known Virtual Router attributes, to be moved from the user template
|
||||
* to the template
|
||||
*/
|
||||
static const char* VROUTER_ATTRIBUTES[];
|
||||
static const int NUM_VROUTER_ATTRIBUTES;
|
||||
|
||||
/**
|
||||
* Parse a string and substitute variables (e.g. $NAME) using the VM
|
||||
* template values:
|
||||
* @param attribute, the string to be parsed
|
||||
* @param parsed, the resulting parsed string
|
||||
* @param error description in case of failure
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int parse_template_attribute(const string& attribute,
|
||||
string& parsed,
|
||||
string& error);
|
||||
|
||||
/**
|
||||
* Parse a file string variable (i.e. $FILE) using the FILE_DS datastores.
|
||||
* It should be used for OS/DS_KERNEL, OS/DS_INITRD, CONTEXT/DS_FILES.
|
||||
* @param attribute the string to be parsed
|
||||
* @param img_ids ids of the FILE images in the attribute
|
||||
* @param error description in case of failure
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int parse_file_attribute(string attribute,
|
||||
vector<int>& img_ids,
|
||||
string& error);
|
||||
|
||||
/**
|
||||
* Generates image attributes (DS_ID, TM_MAD, SOURCE...) for KERNEL and
|
||||
* INITRD files.
|
||||
@ -1959,12 +2020,11 @@ private:
|
||||
* @param base_name of the attribute "KERNEL", or "INITRD"
|
||||
* @param base_type of the image attribute KERNEL, RAMDISK
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 on success
|
||||
* @return 0 on succes
|
||||
*/
|
||||
int set_os_file(VectorAttribute * os,
|
||||
const string& base_name,
|
||||
Image::ImageType base_type,
|
||||
string& error_str);
|
||||
int set_os_file(VectorAttribute* os, const string& base_name,
|
||||
Image::ImageType base_type, string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "OS" attribute of the template by substituting
|
||||
* $FILE variables
|
||||
@ -1973,49 +2033,6 @@ private:
|
||||
*/
|
||||
int parse_os(string& error_str);
|
||||
|
||||
/**
|
||||
* Attributes not allowed in NIC_DEFAULT to avoid authorization bypass and
|
||||
* inconsistencies for NIC_DEFAULTS
|
||||
*/
|
||||
static const char * NO_NIC_DEFAULTS[];
|
||||
|
||||
static const int NUM_NO_NIC_DEFAULTS;
|
||||
|
||||
/**
|
||||
* Parse and generate the ETH_ network attributed of a NIC
|
||||
* @param context attribute
|
||||
* @param nic attribute
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
void parse_nic_context(VectorAttribute * context, VectorAttribute * nic);
|
||||
|
||||
/**
|
||||
* Generate the NETWORK related CONTEXT setions, i.e. ETH_*. This function
|
||||
* is invoked when ever the context is prepared for the VM to capture
|
||||
* netowrking updates.
|
||||
* @param context attribute of the VM
|
||||
* @param error string if any
|
||||
* @return 0 on success
|
||||
*/
|
||||
int generate_network_context(VectorAttribute * context, string& error);
|
||||
|
||||
/**
|
||||
* Generate the PCI related CONTEXT setions, i.e. PCI_*. This function
|
||||
* is also adds basic network attributes for pass-through NICs
|
||||
* @param context attribute of the VM
|
||||
* @return true if the net context was generated.
|
||||
*/
|
||||
bool generate_pci_context(VectorAttribute * context);
|
||||
|
||||
/**
|
||||
* Generate the ONE_GATE token & url
|
||||
* @param context attribute of the VM
|
||||
* @param error_str describing the error
|
||||
* @return 0 if success
|
||||
*/
|
||||
int generate_token_context(VectorAttribute * context, string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "NIC_DEFAULT" attribute
|
||||
* @param error_str Returns the error reason, if any
|
||||
@ -2031,12 +2048,35 @@ private:
|
||||
int parse_vrouter(string& error_str);
|
||||
|
||||
/**
|
||||
* Known Virtual Router attributes, to be moved from the user template
|
||||
* to the template
|
||||
* Parse the "PCI" attribute of the template and checks mandatory attributes
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 on success
|
||||
*/
|
||||
static const char* VROUTER_ATTRIBUTES[];
|
||||
static const int NUM_VROUTER_ATTRIBUTES;
|
||||
int parse_pci(string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "SCHED_REQUIREMENTS" attribute of the template by substituting
|
||||
* $VARIABLE, $VARIABLE[ATTR] and $VARIABLE[ATTR, ATTR = VALUE]
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 on success
|
||||
*/
|
||||
int parse_requirements(string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "GRAPHICS" attribute and generates a default PORT if not
|
||||
* defined
|
||||
*/
|
||||
int parse_graphics(string& error_str);
|
||||
|
||||
/**
|
||||
* Searches the meaningful attributes and moves them from the user template
|
||||
* to the internal template
|
||||
*/
|
||||
void parse_well_known_attributes();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Context related functions
|
||||
// -------------------------------------------------------------------------
|
||||
/**
|
||||
* Known attributes for network contextualization rendered as:
|
||||
* ETH_<nicid>_<context[0]> = $NETWORK[context[1], vnet_name]
|
||||
@ -2066,11 +2106,30 @@ private:
|
||||
static const int NUM_NETWORK6_CONTEXT;
|
||||
|
||||
/**
|
||||
* Parse the "PCI" attribute of the template and checks mandatory attributes
|
||||
* @param error_str Returns the error reason, if any
|
||||
* Generate the NETWORK related CONTEXT setions, i.e. ETH_*. This function
|
||||
* is invoked when ever the context is prepared for the VM to capture
|
||||
* netowrking updates.
|
||||
* @param context attribute of the VM
|
||||
* @param error string if any
|
||||
* @return 0 on success
|
||||
*/
|
||||
int parse_pci(string& error_str);
|
||||
int generate_network_context(VectorAttribute * context, string& error);
|
||||
|
||||
/**
|
||||
* Generate the PCI related CONTEXT setions, i.e. PCI_*. This function
|
||||
* is also adds basic network attributes for pass-through NICs
|
||||
* @param context attribute of the VM
|
||||
* @return true if the net context was generated.
|
||||
*/
|
||||
bool generate_pci_context(VectorAttribute * context);
|
||||
|
||||
/**
|
||||
* Generate the ONE_GATE token & url
|
||||
* @param context attribute of the VM
|
||||
* @param error_str describing the error
|
||||
* @return 0 if success
|
||||
*/
|
||||
int generate_token_context(VectorAttribute * context, string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "CONTEXT" attribute of the template by substituting
|
||||
@ -2091,44 +2150,6 @@ private:
|
||||
*/
|
||||
int parse_context_variables(VectorAttribute ** context, string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "SCHED_REQUIREMENTS" attribute of the template by substituting
|
||||
* $VARIABLE, $VARIABLE[ATTR] and $VARIABLE[ATTR, ATTR = VALUE]
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 on success
|
||||
*/
|
||||
int parse_requirements(string& error_str);
|
||||
|
||||
/**
|
||||
* Parse the "GRAPHICS" attribute and generates a default PORT if not
|
||||
* defined
|
||||
*/
|
||||
int parse_graphics(string& error_str);
|
||||
|
||||
/**
|
||||
* Searches the meaningful attributes and moves them from the user template
|
||||
* to the internal template
|
||||
*/
|
||||
void parse_well_known_attributes();
|
||||
|
||||
/**
|
||||
* Function that renders the VM in XML format optinally including
|
||||
* extended information (all history records)
|
||||
* @param xml the resulting XML string
|
||||
* @param n_history Number of history records to include:
|
||||
* 0: none
|
||||
* 1: the last one
|
||||
* 2: all
|
||||
* @return a reference to the generated string
|
||||
*/
|
||||
string& to_xml_extended(string& xml, int n_history) const;
|
||||
|
||||
/**
|
||||
* Merges NIC_DEFAULT with the given NIC
|
||||
* @param nic NIC to process
|
||||
*/
|
||||
void merge_nic_defaults(VectorAttribute* nic);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// NIC & DISK Management Helpers
|
||||
// -------------------------------------------------------------------------
|
||||
@ -2155,6 +2176,12 @@ private:
|
||||
*/
|
||||
VectorAttribute* get_attach_nic();
|
||||
|
||||
/**
|
||||
* Merges NIC_DEFAULT with the given NIC
|
||||
* @param nic NIC to process
|
||||
*/
|
||||
void merge_nic_defaults(VectorAttribute* nic);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Public cloud templates related functions
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -169,17 +169,9 @@ class VirtualMachineAttributeSet
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Creates the VirtualMachineAttribute set from the Template or vector with
|
||||
* all the attributes.
|
||||
* @param a_name the attribute name (e.g. "DISK")
|
||||
* @param id_name to search for attributes (e.g. "DISK_ID")
|
||||
* Creates the VirtualMachineAttribute set
|
||||
* @param dispose elements upon set destruction
|
||||
*/
|
||||
VirtualMachineAttributeSet(const std::string a_name,
|
||||
const std::string& id_name, Template * tmpl);
|
||||
|
||||
VirtualMachineAttributeSet(const std::string& id_name,
|
||||
std::vector<VectorAttribute *>& vas, bool dispose);
|
||||
|
||||
VirtualMachineAttributeSet(bool _dispose):dispose(_dispose){};
|
||||
|
||||
virtual ~VirtualMachineAttributeSet();
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
|
||||
void clear_active_snapshot()
|
||||
{
|
||||
set_flag("DISK_SNAPSHOT_ACTIVE");
|
||||
clear_flag("DISK_SNAPSHOT_ACTIVE");
|
||||
};
|
||||
|
||||
bool is_active_snapshot()
|
||||
@ -92,6 +92,16 @@ public:
|
||||
return is_flag("DISK_SNAPSHOT_ACTIVE");
|
||||
}
|
||||
|
||||
void set_saveas()
|
||||
{
|
||||
set_flag("HOTPLUG_SAVE_AS_ACTIVE");
|
||||
};
|
||||
|
||||
void clear_saveas()
|
||||
{
|
||||
clear_flag("HOTPLUG_SAVE_AS_ACTIVE");
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Disk attributes, not accesible through vector_value */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -243,7 +253,14 @@ public:
|
||||
* @param tmpl template with DISK
|
||||
*/
|
||||
VirtualMachineDisks(Template * tmpl, bool has_id):
|
||||
VirtualMachineAttributeSet(DISK_NAME, id_name(has_id), tmpl){};
|
||||
VirtualMachineAttributeSet(false)
|
||||
{
|
||||
std::vector<VectorAttribute *> vas;
|
||||
|
||||
tmpl->get(DISK_NAME, vas);
|
||||
|
||||
init(vas, has_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the VirtualMachineDisk set from a vector of DISK VectorAttribute
|
||||
@ -251,7 +268,10 @@ public:
|
||||
* @param va vector of DISK Vector Attributes
|
||||
*/
|
||||
VirtualMachineDisks(vector<VectorAttribute *>& va, bool has_id, bool dispose):
|
||||
VirtualMachineAttributeSet(id_name(has_id), va, dispose){};
|
||||
VirtualMachineAttributeSet(dispose)
|
||||
{
|
||||
init(va, has_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an empty disk set
|
||||
@ -401,6 +421,22 @@ public:
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Attach disk Interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Clear attach status from the attach disk (ATTACH=YES)
|
||||
*/
|
||||
VirtualMachineDisk * delete_attach()
|
||||
{
|
||||
return static_cast<VirtualMachineDisk *>(remove_attribute("ATTACH"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attach disk (ATTACH=YES)
|
||||
*/
|
||||
VirtualMachineDisk * get_attach()
|
||||
{
|
||||
return static_cast<VirtualMachineDisk *>(get_attribute("ATTACH"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attach attribute to the given disk
|
||||
* @param disk_id of the DISK
|
||||
@ -416,16 +452,6 @@ public:
|
||||
clear_flag("ATTACH");
|
||||
}
|
||||
|
||||
VirtualMachineDisk * delete_attach()
|
||||
{
|
||||
return static_cast<VirtualMachineDisk *>(remove_attribute("ATTACH"));
|
||||
}
|
||||
|
||||
VirtualMachineDisk * get_attach()
|
||||
{
|
||||
return static_cast<VirtualMachineDisk *>(get_attribute("ATTACH"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a disk to be attached to the virtual machine and adds it to the
|
||||
* disk set. It checks target assigment and cluster compatibility.
|
||||
@ -441,6 +467,59 @@ public:
|
||||
VirtualMachineDisk * set_up_attach(int vmid, int uid, int cluster_id,
|
||||
VectorAttribute * vdisk, VectorAttribute * vcontext, string& error);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Save as Interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Get the saveas disk (HOTPLUG_SAVE_AS_ACTIVE = YES)
|
||||
*/
|
||||
VirtualMachineDisk * get_saveas()
|
||||
{
|
||||
return static_cast<VirtualMachineDisk *>(
|
||||
get_attribute("HOTPLUG_SAVE_AS_ACTIVE"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the disk that is going to be "save as"
|
||||
* @param disk_id of the VM
|
||||
* @param snap_id of the disk to save, -1 to select the active snapshot
|
||||
* @param iid The image id used by the disk
|
||||
* @param size The disk size. This may be different to the original
|
||||
* image size
|
||||
* @param err_str describing the error if any
|
||||
* @return -1 if the image cannot saveas, 0 on success
|
||||
*/
|
||||
int set_saveas(int disk_id, int snap_id, int &iid, long long &size,
|
||||
string& err_str);
|
||||
|
||||
/**
|
||||
* Set save attributes for the disk
|
||||
* @param disk_id Index of the disk to save
|
||||
* @param source to save the disk
|
||||
* @param img_id ID of the image this disk will be saved to
|
||||
*/
|
||||
int set_saveas(int disk_id, const string& source, int iid);
|
||||
|
||||
/**
|
||||
* Clears the SAVE_AS_* attributes of the disk being saved as
|
||||
* @return the ID of the image this disk will be saved to or -1 if it
|
||||
* is not found.
|
||||
*/
|
||||
int clear_saveas();
|
||||
|
||||
/**
|
||||
* Get the original image id of the disk. It also checks that the disk can
|
||||
* be saved_as.
|
||||
* @param disk_id Index of the disk to save
|
||||
* @param source of the image to save the disk to
|
||||
* @param image_id of the image to save the disk to
|
||||
* @param tm_mad in use by the disk
|
||||
* @param ds_id of the datastore in use by the disk
|
||||
* @return -1 if failure
|
||||
*/
|
||||
int get_saveas_info(int& disk_id, string& source, int& image_id,
|
||||
string& snap_id, string& tm_mad, string& ds_id);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Resize disk Interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -467,9 +546,25 @@ public:
|
||||
return static_cast<VirtualMachineDisk *>(get_attribute("RESIZE"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a disk to be resized.
|
||||
* @param disk_id of disk
|
||||
* @param size new size for the disk (needs to be greater than current)
|
||||
* @param error
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int set_up_resize(int disk_id, long size, string& error);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* SNAPSHOT interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
VirtualMachineDisk * get_active_snapshot()
|
||||
{
|
||||
return static_cast<VirtualMachineDisk *>(
|
||||
get_attribute("DISK_SNAPSHOT_ACTIVE"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the snapshots for a disk
|
||||
* @param id of disk
|
||||
@ -562,18 +657,6 @@ private:
|
||||
void assign_disk_targets(
|
||||
std::queue<pair <std::string, VirtualMachineDisk *> >& dqueue,
|
||||
std::set<std::string>& used_targets);
|
||||
|
||||
static const char * id_name(bool has_id)
|
||||
{
|
||||
if (has_id)
|
||||
{
|
||||
return DISK_ID_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*VIRTUAL_MACHINE_DISK_H_*/
|
||||
|
@ -815,6 +815,7 @@ VM_RESTRICTED_ATTR = "DISK/READ_IOPS_SEC"
|
||||
VM_RESTRICTED_ATTR = "DISK/WRITE_IOPS_SEC"
|
||||
#VM_RESTRICTED_ATTR = "DISK/SIZE"
|
||||
VM_RESTRICTED_ATTR = "DISK/ORIGINAL_SIZE"
|
||||
VM_RESTRICTED_ATTR = "DISK/SIZE_PREV"
|
||||
VM_RESTRICTED_ATTR = "CPU_COST"
|
||||
VM_RESTRICTED_ATTR = "MEMORY_COST"
|
||||
VM_RESTRICTED_ATTR = "DISK_COST"
|
||||
|
@ -31,7 +31,7 @@ require 'nokogiri'
|
||||
|
||||
module OneDBFsck
|
||||
VERSION = "5.2.0"
|
||||
LOCAL_VERSION = "4.90.0"
|
||||
LOCAL_VERSION = "5.2.0"
|
||||
|
||||
def check_db_version()
|
||||
db_version = read_db_version()
|
||||
|
@ -51,6 +51,8 @@ source_files=[
|
||||
'VirtualMachineAttribute.cc',
|
||||
'VirtualMachineDisk.cc',
|
||||
'VirtualMachineSystemSnapshot.cc',
|
||||
'VirtualMachineParser.cc',
|
||||
'VirtualMachineContext.cc',
|
||||
'Snapshots.cc'
|
||||
]
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,26 +16,6 @@
|
||||
|
||||
#include "VirtualMachineAttribute.h"
|
||||
|
||||
|
||||
VirtualMachineAttributeSet::VirtualMachineAttributeSet(const std::string anam,
|
||||
const std::string& idnam, Template * tmpl):dispose(false)
|
||||
{
|
||||
std::vector<VectorAttribute *> vas;
|
||||
|
||||
tmpl->get(anam, vas);
|
||||
|
||||
init_attribute_map(idnam, vas);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
VirtualMachineAttributeSet::VirtualMachineAttributeSet(const std::string& idnam,
|
||||
std::vector<VectorAttribute *>& vas, bool _dispose):dispose(_dispose)
|
||||
{
|
||||
init_attribute_map(idnam, vas);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
579
src/vm/VirtualMachineContext.cc
Normal file
579
src/vm/VirtualMachineContext.cc
Normal file
@ -0,0 +1,579 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
|
||||
#include "VirtualMachine.h"
|
||||
#include "VirtualNetworkPool.h"
|
||||
#include "ImagePool.h"
|
||||
#include "NebulaLog.h"
|
||||
#include "NebulaUtil.h"
|
||||
#include "Snapshots.h"
|
||||
|
||||
#include "Nebula.h"
|
||||
|
||||
#include "vm_file_var_syntax.h"
|
||||
#include "vm_var_syntax.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Context constants */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
const char * VirtualMachine::NETWORK_CONTEXT[][2] = {
|
||||
{"IP", "IP"},
|
||||
{"MAC", "MAC"},
|
||||
{"MASK", "NETWORK_MASK"},
|
||||
{"NETWORK", "NETWORK_ADDRESS"},
|
||||
{"GATEWAY", "GATEWAY"},
|
||||
{"DNS", "DNS"},
|
||||
{"SEARCH_DOMAIN", "SEARCH_DOMAIN"},
|
||||
{"MTU", "GUEST_MTU"},
|
||||
{"VLAN_ID", "VLAN_ID"},
|
||||
{"VROUTER_IP", "VROUTER_IP"},
|
||||
{"VROUTER_MANAGEMENT", "VROUTER_MANAGEMENT"}};
|
||||
const int VirtualMachine::NUM_NETWORK_CONTEXT = 11;
|
||||
|
||||
const char* VirtualMachine::NETWORK6_CONTEXT[][2] = {
|
||||
{"IP6", "IP6_GLOBAL"},
|
||||
{"IP6_ULA", "IP6_ULA"},
|
||||
{"GATEWAY6", "GATEWAY6"},
|
||||
{"CONTEXT_FORCE_IPV4", "CONTEXT_FORCE_IPV4"},
|
||||
{"VROUTER_IP6", "VROUTER_IP6_GLOBAL"}};
|
||||
|
||||
const int VirtualMachine::NUM_NETWORK6_CONTEXT = 5;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* CONTEXT - Public Interface */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::generate_context(string &files, int &disk_id,
|
||||
const string& token_password)
|
||||
{
|
||||
ofstream file;
|
||||
string files_ds, error_str;
|
||||
|
||||
vector<const VectorAttribute*> attrs;
|
||||
|
||||
map<string, string>::const_iterator it;
|
||||
|
||||
files = "";
|
||||
bool token;
|
||||
|
||||
if ( history == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
VectorAttribute * context = obj_template->get("CONTEXT");
|
||||
|
||||
if ( context == 0 )
|
||||
{
|
||||
log("VM", Log::INFO, "Virtual Machine has no context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Generate dynamic context attributes
|
||||
if ( generate_network_context(context, error_str) != 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Cannot parse network context:: " << error_str;
|
||||
log("VM", Log::ERROR, oss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
file.open(history->context_file.c_str(),ios::out);
|
||||
|
||||
if (file.fail() == true)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Could not open context file: " << history->context_file;
|
||||
log("VM", Log::ERROR, oss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
files = context->vector_value("FILES");
|
||||
files_ds = context->vector_value("FILES_DS");
|
||||
|
||||
if (!files_ds.empty())
|
||||
{
|
||||
files += " ";
|
||||
files += files_ds;
|
||||
}
|
||||
|
||||
for (size_t i=0;i<files.length();i++)
|
||||
{
|
||||
if (files[i] == '\n')
|
||||
{
|
||||
files[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
context->vector_value("TOKEN", token);
|
||||
|
||||
if (token)
|
||||
{
|
||||
ofstream token_file;
|
||||
ostringstream oss;
|
||||
|
||||
string* encrypted;
|
||||
string tk_error;
|
||||
|
||||
if (token_password.empty())
|
||||
{
|
||||
tk_error = "Cannot generate OneGate token: TOKEN_PASSWORD not set in"
|
||||
" the user template.";
|
||||
file.close();
|
||||
|
||||
log("VM", Log::ERROR, tk_error.c_str());
|
||||
set_template_error_message(tk_error);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
token_file.open(history->token_file.c_str(), ios::out);
|
||||
|
||||
if (token_file.fail())
|
||||
{
|
||||
tk_error = "Cannot create token file";
|
||||
|
||||
file.close();
|
||||
|
||||
log("VM", Log::ERROR, tk_error.c_str());
|
||||
set_template_error_message(tk_error);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
oss << oid << ':' << stime;
|
||||
|
||||
encrypted = one_util::aes256cbc_encrypt(oss.str(), token_password);
|
||||
|
||||
token_file << *encrypted << endl;
|
||||
|
||||
token_file.close();
|
||||
|
||||
delete encrypted;
|
||||
|
||||
files += (" " + history->token_file);
|
||||
}
|
||||
|
||||
const map<string, string> values = context->value();
|
||||
|
||||
file << "# Context variables generated by OpenNebula\n";
|
||||
|
||||
for (it=values.begin(); it != values.end(); it++ )
|
||||
{
|
||||
//Replace every ' in value by '\''
|
||||
string escape_str(it->second);
|
||||
size_t pos = 0;
|
||||
|
||||
while ((pos = escape_str.find('\'', pos)) != string::npos)
|
||||
{
|
||||
escape_str.replace(pos,1,"'\\''");
|
||||
pos = pos + 4;
|
||||
}
|
||||
|
||||
file << it->first <<"='" << escape_str << "'" << endl;
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
context->vector_value("DISK_ID", disk_id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::get_created_by_uid() const
|
||||
{
|
||||
int created_by_uid;
|
||||
|
||||
if (obj_template->get("CREATED_BY", created_by_uid))
|
||||
{
|
||||
return created_by_uid;
|
||||
}
|
||||
|
||||
return get_uid();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* CONTEXT - Private Interface */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void parse_context_network(const char* vars[][2], int num_vars,
|
||||
VectorAttribute * context, VectorAttribute * nic)
|
||||
{
|
||||
string nic_id = nic->vector_value("NIC_ID");
|
||||
|
||||
for (int i=0; i < num_vars; i++)
|
||||
{
|
||||
ostringstream cvar;
|
||||
string cval;
|
||||
|
||||
cvar << "ETH" << nic_id << "_" << vars[i][0];
|
||||
|
||||
cval = nic->vector_value(vars[i][1]); //Check the NIC
|
||||
|
||||
if (cval.empty()) //Will check the AR and VNET
|
||||
{
|
||||
ostringstream cval_ss;
|
||||
|
||||
cval_ss << "$NETWORK["<< vars[i][1] <<", NIC_ID=\""<< nic_id <<"\"]";
|
||||
cval = cval_ss.str();
|
||||
}
|
||||
|
||||
context->replace(cvar.str(), cval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int VirtualMachine::generate_network_context(VectorAttribute* context,
|
||||
string& error_str)
|
||||
{
|
||||
bool net_context;
|
||||
|
||||
context->vector_value("NETWORK", net_context);
|
||||
|
||||
if (!net_context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector<VectorAttribute *> vatts;
|
||||
int rc;
|
||||
|
||||
string parsed;
|
||||
string* str;
|
||||
|
||||
VectorAttribute tmp_context("TMP_CONTEXT");
|
||||
|
||||
int num_vatts = obj_template->get("NIC", vatts);
|
||||
|
||||
if ( num_vatts == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i=0; i<num_vatts; i++)
|
||||
{
|
||||
parse_context_network(NETWORK_CONTEXT, NUM_NETWORK_CONTEXT,
|
||||
&tmp_context, vatts[i]);
|
||||
parse_context_network(NETWORK6_CONTEXT, NUM_NETWORK6_CONTEXT,
|
||||
&tmp_context, vatts[i]);
|
||||
}
|
||||
|
||||
str = tmp_context.marshall();
|
||||
|
||||
if (str == 0)
|
||||
{
|
||||
error_str = "Internal error generating network context";
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = parse_template_attribute(*str, parsed, error_str);
|
||||
|
||||
delete str;
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp_context.clear();
|
||||
|
||||
tmp_context.unmarshall(parsed);
|
||||
|
||||
context->merge(&tmp_context, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void parse_pci_context_network(const char* vars[][2], int num_vars,
|
||||
VectorAttribute * context, VectorAttribute * nic)
|
||||
{
|
||||
string pci_id = nic->vector_value("PCI_ID");
|
||||
|
||||
for (int i=0; i < num_vars; i++)
|
||||
{
|
||||
ostringstream cvar;
|
||||
|
||||
cvar << "PCI" << pci_id << "_" << vars[i][0];
|
||||
|
||||
string cval = nic->vector_value(vars[i][1]);
|
||||
|
||||
if (!cval.empty())
|
||||
{
|
||||
context->replace(cvar.str(), cval);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the PCI related CONTEXT setions, i.e. PCI_*. This function
|
||||
* is also adds basic network attributes for pass-through NICs
|
||||
* @param context attribute of the VM
|
||||
* @return true if the net context was generated.
|
||||
*/
|
||||
bool VirtualMachine::generate_pci_context(VectorAttribute * context)
|
||||
{
|
||||
bool net_context;
|
||||
vector<VectorAttribute *> vatts;
|
||||
|
||||
context->vector_value("NETWORK", net_context);
|
||||
|
||||
int num_vatts = obj_template->get("PCI", vatts);
|
||||
|
||||
for(int i=0; i<num_vatts; i++)
|
||||
{
|
||||
if ( net_context && vatts[i]->vector_value("TYPE") == "NIC" )
|
||||
{
|
||||
parse_pci_context_network(NETWORK_CONTEXT, NUM_NETWORK_CONTEXT,
|
||||
context, vatts[i]);
|
||||
parse_pci_context_network(NETWORK6_CONTEXT, NUM_NETWORK6_CONTEXT,
|
||||
context, vatts[i]);
|
||||
}
|
||||
|
||||
ostringstream cvar;
|
||||
|
||||
cvar << "PCI" << vatts[i]->vector_value("PCI_ID") << "_ADDRESS";
|
||||
|
||||
string cval = vatts[i]->vector_value("VM_ADDRESS");
|
||||
|
||||
if (!cval.empty())
|
||||
{
|
||||
context->replace(cvar.str(), cval);
|
||||
}
|
||||
}
|
||||
|
||||
return net_context;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::generate_token_context(VectorAttribute * context, string& e)
|
||||
{
|
||||
bool token;
|
||||
string ep;
|
||||
|
||||
context->vector_value("TOKEN", token);
|
||||
|
||||
if ( token == false )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Nebula::instance().get_configuration_attribute("ONEGATE_ENDPOINT", ep);
|
||||
|
||||
if ( ep.empty() )
|
||||
{
|
||||
e = "TOKEN set, but onegate endpoint was not defined in oned.conf.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
context->replace("ONEGATE_ENDPOINT", ep);
|
||||
context->replace("VMID", oid);
|
||||
|
||||
// Store the original owner to compute token_password in case of a chown
|
||||
replace_template_attribute("CREATED_BY", uid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_context(string& error_str)
|
||||
{
|
||||
VectorAttribute * context = obj_template->get("CONTEXT");
|
||||
|
||||
if ( context == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
string files_ds = context->vector_value("FILES_DS");
|
||||
|
||||
context->remove("FILES_DS");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Add network context and parse variables
|
||||
// -------------------------------------------------------------------------
|
||||
if (parse_context_variables(&context, error_str) == -1 ||
|
||||
generate_network_context(context, error_str) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
generate_pci_context(context);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Parse FILE_DS variables
|
||||
// -------------------------------------------------------------------------
|
||||
if (!files_ds.empty())
|
||||
{
|
||||
string files_ds_parsed;
|
||||
string st;
|
||||
|
||||
ostringstream oss_parsed;
|
||||
|
||||
vector<int> img_ids;
|
||||
|
||||
if ( parse_file_attribute(files_ds, img_ids, error_str) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( img_ids.size() > 0 )
|
||||
{
|
||||
vector<int>::iterator it;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
ImagePool * ipool = nd.get_ipool();
|
||||
Image * img = 0;
|
||||
|
||||
Image::ImageType type;
|
||||
Image::ImageState state;
|
||||
|
||||
for ( it=img_ids.begin() ; it < img_ids.end(); it++ )
|
||||
{
|
||||
img = ipool->get(*it, true);
|
||||
|
||||
if ( img != 0 )
|
||||
{
|
||||
oss_parsed << img->get_source() << ":'"
|
||||
<< img->get_name() << "' ";
|
||||
|
||||
type = img->get_type();
|
||||
state = img->get_state();
|
||||
|
||||
img->unlock();
|
||||
|
||||
if (type != Image::CONTEXT)
|
||||
{
|
||||
error_str = "Only images of type CONTEXT can be used in"
|
||||
" FILE_DS attribute.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( state != Image::READY )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << Image::type_to_str(type)
|
||||
<< " Image '" << *it << "' not in READY state.";
|
||||
|
||||
error_str = oss.str();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
files_ds_parsed = oss_parsed.str();
|
||||
|
||||
if ( !files_ds_parsed.empty() )
|
||||
{
|
||||
context->replace("FILES_DS", files_ds_parsed);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// OneGate URL
|
||||
// -------------------------------------------------------------------------
|
||||
if ( generate_token_context(context, error_str) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Virtual Router attributes
|
||||
// -------------------------------------------------------------------------
|
||||
string st;
|
||||
|
||||
for (int i = 0; i < NUM_VROUTER_ATTRIBUTES; i++)
|
||||
{
|
||||
obj_template->get(VROUTER_ATTRIBUTES[i], st);
|
||||
|
||||
if (!st.empty())
|
||||
{
|
||||
context->replace(VROUTER_ATTRIBUTES[i], st);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_context_variables(VectorAttribute ** context,
|
||||
string& error_str)
|
||||
{
|
||||
int rc;
|
||||
|
||||
string parsed;
|
||||
string * str = (*context)->marshall();
|
||||
|
||||
if (str == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = parse_template_attribute(*str, parsed, error_str);
|
||||
|
||||
delete str;
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*context = new VectorAttribute("CONTEXT");
|
||||
(*context)->unmarshall(parsed);
|
||||
|
||||
obj_template->erase("CONTEXT");
|
||||
obj_template->set(*context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -368,7 +368,7 @@ long long VirtualMachineDisks::system_ds_size()
|
||||
|
||||
long long VirtualMachineDisks::system_ds_size(Template * ds_tmpl)
|
||||
{
|
||||
VirtualMachineDisks disks(ds_tmpl);
|
||||
VirtualMachineDisks disks(ds_tmpl, false);
|
||||
|
||||
return disks.system_ds_size();
|
||||
}
|
||||
@ -386,7 +386,7 @@ void VirtualMachineDisks::extended_info(int uid)
|
||||
|
||||
void VirtualMachineDisks::extended_info(int uid, Template * tmpl)
|
||||
{
|
||||
VirtualMachineDisks disks(tmpl);
|
||||
VirtualMachineDisks disks(tmpl, false);
|
||||
|
||||
return disks.extended_info(uid);
|
||||
}
|
||||
@ -415,8 +415,6 @@ bool VirtualMachineDisks::volatile_info(int ds_id)
|
||||
return found;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@ -477,140 +475,6 @@ void VirtualMachineDisks::assign_disk_targets(
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
VirtualMachineDisk * VirtualMachineDisks::set_up_attach(int vmid, int uid,
|
||||
int cluster_id, VectorAttribute * vdisk, VectorAttribute * vcontext,
|
||||
string& error)
|
||||
{
|
||||
set<string> used_targets;
|
||||
int max_disk_id = -1;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Get the list of used targets and max_disk_id
|
||||
// -------------------------------------------------------------------------
|
||||
for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
|
||||
{
|
||||
string target = (*disk)->vector_value("TARGET");
|
||||
|
||||
if ( !target.empty() )
|
||||
{
|
||||
used_targets.insert(target);
|
||||
}
|
||||
|
||||
int disk_id = (*disk)->get_disk_id();
|
||||
|
||||
if ( disk_id > max_disk_id )
|
||||
{
|
||||
max_disk_id = disk_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vcontext != 0 )
|
||||
{
|
||||
string target = vcontext->vector_value("TARGET");
|
||||
|
||||
if ( !target.empty() )
|
||||
{
|
||||
used_targets.insert(target);
|
||||
}
|
||||
|
||||
int disk_id;
|
||||
|
||||
vcontext->vector_value("DISK_ID", disk_id);
|
||||
|
||||
if ( disk_id > max_disk_id )
|
||||
{
|
||||
max_disk_id = disk_id;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Acquire the new disk image
|
||||
// -------------------------------------------------------------------------
|
||||
Nebula& nd = Nebula::instance();
|
||||
ImagePool * ipool = nd.get_ipool();
|
||||
ImageManager* imagem = nd.get_imagem();
|
||||
|
||||
Snapshots * snap = 0;
|
||||
|
||||
string dev_prefix;
|
||||
Image::ImageType img_type;
|
||||
|
||||
int image_id;
|
||||
|
||||
VirtualMachineDisk * disk = new VirtualMachineDisk(vdisk, max_disk_id + 1);
|
||||
|
||||
int rc = ipool->acquire_disk(vmid, disk, max_disk_id + 1, img_type,
|
||||
dev_prefix, uid, image_id, &snap, error);
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
disk->set_snapshots(snap);
|
||||
|
||||
string target = disk->vector_value("TARGET");
|
||||
|
||||
if ( !target.empty() )
|
||||
{
|
||||
if ( used_targets.insert(target).second == false )
|
||||
{
|
||||
error = "Target " + target + " is already in use.";
|
||||
|
||||
imagem->release_image(vmid, image_id, false);
|
||||
|
||||
delete disk;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
queue<pair <string, VirtualMachineDisk *> > disks_queue;
|
||||
|
||||
disks_queue.push(make_pair(dev_prefix, disk));
|
||||
|
||||
assign_disk_targets(disks_queue, used_targets);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check that we don't have a cluster incompatibility.
|
||||
// -------------------------------------------------------------------------
|
||||
string disk_cluster_ids = disk->vector_value("CLUSTER_ID");
|
||||
|
||||
if ( !disk_cluster_ids.empty() )
|
||||
{
|
||||
set<int> cluster_ids;
|
||||
one_util::split_unique(disk_cluster_ids, ',', cluster_ids);
|
||||
|
||||
if (cluster_ids.count(cluster_id) == 0)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Image [" << image_id << "] is not part of cluster ["
|
||||
<< cluster_id << "]";
|
||||
|
||||
error = oss.str();
|
||||
|
||||
imagem->release_image(vmid, image_id, false);
|
||||
|
||||
delete disk;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Add disk to the set
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
disk->set_attach();
|
||||
|
||||
add_attribute(disk, disk->get_disk_id());
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachineDisks::get_images(int vm_id, int uid,
|
||||
vector<Attribute *> disks, VectorAttribute * vcontext,
|
||||
std::string& error_str)
|
||||
@ -875,6 +739,140 @@ int VirtualMachineDisks::set_attach(int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
VirtualMachineDisk * VirtualMachineDisks::set_up_attach(int vmid, int uid,
|
||||
int cluster_id, VectorAttribute * vdisk, VectorAttribute * vcontext,
|
||||
string& error)
|
||||
{
|
||||
set<string> used_targets;
|
||||
int max_disk_id = -1;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Get the list of used targets and max_disk_id
|
||||
// -------------------------------------------------------------------------
|
||||
for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
|
||||
{
|
||||
string target = (*disk)->vector_value("TARGET");
|
||||
|
||||
if ( !target.empty() )
|
||||
{
|
||||
used_targets.insert(target);
|
||||
}
|
||||
|
||||
int disk_id = (*disk)->get_disk_id();
|
||||
|
||||
if ( disk_id > max_disk_id )
|
||||
{
|
||||
max_disk_id = disk_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vcontext != 0 )
|
||||
{
|
||||
string target = vcontext->vector_value("TARGET");
|
||||
|
||||
if ( !target.empty() )
|
||||
{
|
||||
used_targets.insert(target);
|
||||
}
|
||||
|
||||
int disk_id;
|
||||
|
||||
vcontext->vector_value("DISK_ID", disk_id);
|
||||
|
||||
if ( disk_id > max_disk_id )
|
||||
{
|
||||
max_disk_id = disk_id;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Acquire the new disk image
|
||||
// -------------------------------------------------------------------------
|
||||
Nebula& nd = Nebula::instance();
|
||||
ImagePool * ipool = nd.get_ipool();
|
||||
ImageManager* imagem = nd.get_imagem();
|
||||
|
||||
Snapshots * snap = 0;
|
||||
|
||||
string dev_prefix;
|
||||
Image::ImageType img_type;
|
||||
|
||||
int image_id;
|
||||
|
||||
VirtualMachineDisk * disk = new VirtualMachineDisk(vdisk, max_disk_id + 1);
|
||||
|
||||
int rc = ipool->acquire_disk(vmid, disk, max_disk_id + 1, img_type,
|
||||
dev_prefix, uid, image_id, &snap, error);
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
disk->set_snapshots(snap);
|
||||
|
||||
string target = disk->vector_value("TARGET");
|
||||
|
||||
if ( !target.empty() )
|
||||
{
|
||||
if ( used_targets.insert(target).second == false )
|
||||
{
|
||||
error = "Target " + target + " is already in use.";
|
||||
|
||||
imagem->release_image(vmid, image_id, false);
|
||||
|
||||
delete disk;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
queue<pair <string, VirtualMachineDisk *> > disks_queue;
|
||||
|
||||
disks_queue.push(make_pair(dev_prefix, disk));
|
||||
|
||||
assign_disk_targets(disks_queue, used_targets);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check that we don't have a cluster incompatibility.
|
||||
// -------------------------------------------------------------------------
|
||||
string disk_cluster_ids = disk->vector_value("CLUSTER_ID");
|
||||
|
||||
if ( !disk_cluster_ids.empty() )
|
||||
{
|
||||
set<int> cluster_ids;
|
||||
one_util::split_unique(disk_cluster_ids, ',', cluster_ids);
|
||||
|
||||
if (cluster_ids.count(cluster_id) == 0)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Image [" << image_id << "] is not part of cluster ["
|
||||
<< cluster_id << "]";
|
||||
|
||||
error = oss.str();
|
||||
|
||||
imagem->release_image(vmid, image_id, false);
|
||||
|
||||
delete disk;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Add disk to the set
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
disk->set_attach();
|
||||
|
||||
add_attribute(disk, disk->get_disk_id());
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* RESIZE DISK INTERFACE */
|
||||
@ -895,6 +893,8 @@ int VirtualMachineDisks::set_resize(int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineDisks::clear_resize(bool restore)
|
||||
{
|
||||
string size, size_prev;
|
||||
@ -914,6 +914,40 @@ void VirtualMachineDisks::clear_resize(bool restore)
|
||||
disk->clear_resize();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachineDisks::set_up_resize(int disk_id, long size, string& err)
|
||||
{
|
||||
VirtualMachineDisk * disk = get_disk(disk_id);
|
||||
long size_prev;
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
err = "Disk not found";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( disk->vector_value("SIZE", size_prev) != 0 )
|
||||
{
|
||||
err = "Wrong format for disk SIZE";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( size <= size_prev )
|
||||
{
|
||||
err = "New size has to be bigger than current one";
|
||||
return -1;
|
||||
}
|
||||
|
||||
disk->replace("SIZE_PREV", size_prev);
|
||||
|
||||
disk->replace("SIZE", size);
|
||||
|
||||
disk->set_resize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* SNAPSHOT INTERFACE */
|
||||
@ -951,15 +985,12 @@ int VirtualMachineDisks::set_active_snapshot(int id, int snap_id)
|
||||
|
||||
void VirtualMachineDisks::clear_active_snapshot()
|
||||
{
|
||||
for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
|
||||
{
|
||||
if ( (*disk)->is_active_snapshot() )
|
||||
{
|
||||
(*disk)->clear_active_snapshot();
|
||||
(*disk)->remove("DISK_SNAPSHOT_ID");
|
||||
VirtualMachineDisk * disk = get_active_snapshot();
|
||||
|
||||
break;
|
||||
}
|
||||
if ( disk != 0 )
|
||||
{
|
||||
disk->clear_active_snapshot();
|
||||
disk->remove("DISK_SNAPSHOT_ID");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1081,7 +1112,7 @@ void VirtualMachineDisks::delete_snapshot(int disk_id, int snap_id,
|
||||
void VirtualMachineDisks::delete_non_persistent_snapshots(Template **vm_quotas,
|
||||
map<int, Template *>& ds_quotas)
|
||||
{
|
||||
long long system_disk;
|
||||
long long system_disk = 0;
|
||||
|
||||
for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
|
||||
{
|
||||
@ -1131,3 +1162,115 @@ void VirtualMachineDisks::delete_non_persistent_snapshots(Template **vm_quotas,
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachineDisks::set_saveas(int disk_id, int snap_id, int &iid,
|
||||
long long &size, string& err_str)
|
||||
{
|
||||
iid = -1;
|
||||
|
||||
VirtualMachineDisk * disk =
|
||||
static_cast<VirtualMachineDisk *>(get_attribute(disk_id));
|
||||
|
||||
if (disk == 0)
|
||||
{
|
||||
err_str = "DISK does not exist.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->vector_value("IMAGE_ID", iid) != 0)
|
||||
{
|
||||
iid = -1;
|
||||
err_str = "DISK does not have a valid IMAGE_ID.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Snapshots * snaps = disk->get_snapshots();
|
||||
|
||||
if (snap_id != -1)
|
||||
{
|
||||
if (snaps == 0 || !snaps->exists(snap_id))
|
||||
{
|
||||
err_str = "Snapshot does not exist.";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
disk->set_saveas();
|
||||
disk->replace("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id);
|
||||
|
||||
size = 0;
|
||||
disk->vector_value("SIZE", size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachineDisks::set_saveas(int disk_id, const string& source, int iid)
|
||||
{
|
||||
VirtualMachineDisk * disk = get_saveas();
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
disk->replace("HOTPLUG_SAVE_AS", iid);
|
||||
disk->replace("HOTPLUG_SAVE_AS_SOURCE", source);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachineDisks::clear_saveas()
|
||||
{
|
||||
VirtualMachineDisk * disk = get_saveas();
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int image_id;
|
||||
|
||||
disk->clear_saveas();
|
||||
|
||||
disk->vector_value("HOTPLUG_SAVE_AS", image_id);
|
||||
|
||||
disk->remove("HOTPLUG_SAVE_AS");
|
||||
disk->remove("HOTPLUG_SAVE_AS_SOURCE");
|
||||
disk->remove("HOTPLUG_SAVE_AS_SNAPSHOT_ID");
|
||||
|
||||
return image_id;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachineDisks::get_saveas_info(int& disk_id, string& source,
|
||||
int& image_id, string& snap_id, string& tm_mad, string& ds_id)
|
||||
{
|
||||
int rc;
|
||||
|
||||
VirtualMachineDisk * disk = get_saveas();
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = disk->vector_value("HOTPLUG_SAVE_AS_SOURCE", source);
|
||||
rc += disk->vector_value("HOTPLUG_SAVE_AS", image_id);
|
||||
rc += disk->vector_value("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id);
|
||||
rc += disk->vector_value("DISK_ID", disk_id);
|
||||
rc += disk->vector_value("DATASTORE_ID", ds_id);
|
||||
rc += disk->vector_value("TM_MAD", tm_mad);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
683
src/vm/VirtualMachineParser.cc
Normal file
683
src/vm/VirtualMachineParser.cc
Normal file
@ -0,0 +1,683 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
|
||||
#include "VirtualMachine.h"
|
||||
#include "VirtualNetworkPool.h"
|
||||
#include "ImagePool.h"
|
||||
#include "NebulaLog.h"
|
||||
#include "NebulaUtil.h"
|
||||
#include "Snapshots.h"
|
||||
|
||||
#include "Nebula.h"
|
||||
|
||||
#include "vm_file_var_syntax.h"
|
||||
#include "vm_var_syntax.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Parser constanta */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const char * VirtualMachine::NO_NIC_DEFAULTS[] = {"NETWORK_ID", "NETWORK",
|
||||
"NETWORK_UID", "NETWORK_UNAME"};
|
||||
|
||||
const int VirtualMachine::NUM_NO_NIC_DEFAULTS = 4;
|
||||
|
||||
const char* VirtualMachine::VROUTER_ATTRIBUTES[] = {
|
||||
"VROUTER_ID",
|
||||
"VROUTER_KEEPALIVED_ID",
|
||||
"VROUTER_KEEPALIVED_PASSWORD"};
|
||||
const int VirtualMachine::NUM_VROUTER_ATTRIBUTES = 3;
|
||||
|
||||
pthread_mutex_t VirtualMachine::lex_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Generates image attributes (DS_ID, TM_MAD, SOURCE...) for KERNEL and
|
||||
* INITRD files.
|
||||
* @param os attribute of the VM template
|
||||
* @param base_name of the attribute "KERNEL", or "INITRD"
|
||||
* @param base_type of the image attribute KERNEL, RAMDISK
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 on succes
|
||||
*/
|
||||
int VirtualMachine::set_os_file(VectorAttribute* os, const string& base_name,
|
||||
Image::ImageType base_type, string& error_str)
|
||||
{
|
||||
vector<int> img_ids;
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
ImagePool * ipool = nd.get_ipool();
|
||||
Image * img = 0;
|
||||
|
||||
int img_id;
|
||||
|
||||
Image::ImageType type;
|
||||
Image::ImageState state;
|
||||
|
||||
DatastorePool * ds_pool = nd.get_dspool();
|
||||
Datastore * ds;
|
||||
int ds_id;
|
||||
|
||||
string attr;
|
||||
string base_name_ds = base_name + "_DS";
|
||||
string base_name_id = base_name + "_DS_ID";
|
||||
string base_name_source = base_name + "_DS_SOURCE";
|
||||
string base_name_ds_id = base_name + "_DS_DSID";
|
||||
string base_name_tm = base_name + "_DS_TM";
|
||||
string base_name_cluster= base_name + "_DS_CLUSTER_ID";
|
||||
|
||||
string type_str;
|
||||
|
||||
attr = os->vector_value(base_name_ds.c_str());
|
||||
|
||||
if ( attr.empty() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( parse_file_attribute(attr, img_ids, error_str) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( img_ids.size() != 1 )
|
||||
{
|
||||
error_str = "Only one FILE variable can be used in: " + attr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
img_id = img_ids.back();
|
||||
|
||||
img = ipool->get(img_id, true);
|
||||
|
||||
if ( img == 0 )
|
||||
{
|
||||
error_str = "Image no longer exists in attribute: " + attr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
state = img->get_state();
|
||||
|
||||
ds_id = img->get_ds_id();
|
||||
type = img->get_type();
|
||||
|
||||
os->remove(base_name);
|
||||
|
||||
os->replace(base_name_id, img->get_oid());
|
||||
os->replace(base_name_source, img->get_source());
|
||||
os->replace(base_name_ds_id, img->get_ds_id());
|
||||
|
||||
img->unlock();
|
||||
|
||||
type_str = Image::type_to_str(type);
|
||||
|
||||
if ( type != base_type )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << base_name << " needs an image of type "
|
||||
<< Image::type_to_str(base_type) << " and not "
|
||||
<< type_str;
|
||||
|
||||
error_str = oss.str();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( state != Image::READY )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << type_str << " Image '" << img_id << " 'not in READY state.";
|
||||
|
||||
error_str = oss.str();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ds = ds_pool->get(ds_id, true);
|
||||
|
||||
if ( ds == 0 )
|
||||
{
|
||||
error_str = "Associated datastore for image does not exist";
|
||||
return -1;
|
||||
}
|
||||
|
||||
os->replace(base_name_tm, ds->get_tm_mad());
|
||||
|
||||
set<int> cluster_ids = ds->get_cluster_ids();
|
||||
|
||||
if (!cluster_ids.empty())
|
||||
{
|
||||
os->replace(base_name_cluster, one_util::join(cluster_ids, ','));
|
||||
}
|
||||
|
||||
ds->unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_os(string& error_str)
|
||||
{
|
||||
int num;
|
||||
int rc;
|
||||
|
||||
vector<Attribute *> os_attr;
|
||||
VectorAttribute * os;
|
||||
|
||||
vector<Attribute *>::iterator it;
|
||||
|
||||
num = user_obj_template->remove("OS", os_attr);
|
||||
|
||||
for (it=os_attr.begin(); it != os_attr.end(); it++)
|
||||
{
|
||||
obj_template->set(*it);
|
||||
}
|
||||
|
||||
if ( num == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ( num > 1 )
|
||||
{
|
||||
error_str = "Only one OS attribute can be defined.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
os = dynamic_cast<VectorAttribute *>(os_attr[0]);
|
||||
|
||||
if ( os == 0 )
|
||||
{
|
||||
error_str = "Internal error parsing OS attribute.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = set_os_file(os, "KERNEL", Image::KERNEL, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = set_os_file(os, "INITRD", Image::RAMDISK, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_defaults(string& error_str)
|
||||
{
|
||||
int num;
|
||||
|
||||
vector<Attribute *> attr;
|
||||
VectorAttribute* vatt = 0;
|
||||
|
||||
num = user_obj_template->remove("NIC_DEFAULT", attr);
|
||||
|
||||
if ( num == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( num > 1 )
|
||||
{
|
||||
error_str = "Only one NIC_DEFAULT attribute can be defined.";
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
vatt = dynamic_cast<VectorAttribute *>(attr[0]);
|
||||
|
||||
if ( vatt == 0 )
|
||||
{
|
||||
error_str = "Wrong format for NIC_DEFAULT attribute.";
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
for (int i=0; i < NUM_NO_NIC_DEFAULTS; i++)
|
||||
{
|
||||
if(vatt->vector_value(NO_NIC_DEFAULTS[i]) != "")
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "Attribute " << NO_NIC_DEFAULTS[i]
|
||||
<< " is not allowed inside NIC_DEFAULT.";
|
||||
|
||||
error_str = oss.str();
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
obj_template->set(vatt);
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup:
|
||||
|
||||
for (int i = 0; i < num ; i++)
|
||||
{
|
||||
delete attr[i];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_vrouter(string& error_str)
|
||||
{
|
||||
string st;
|
||||
|
||||
for (int i = 0; i < NUM_VROUTER_ATTRIBUTES; i++)
|
||||
{
|
||||
user_obj_template->get(VROUTER_ATTRIBUTES[i], st);
|
||||
|
||||
if (!st.empty())
|
||||
{
|
||||
obj_template->replace(VROUTER_ATTRIBUTES[i], st);
|
||||
}
|
||||
|
||||
user_obj_template->erase(VROUTER_ATTRIBUTES[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int check_pci_attributes(VectorAttribute * pci, const string& default_bus,
|
||||
string& error_str)
|
||||
{
|
||||
static string attrs[] = {"VENDOR", "DEVICE", "CLASS"};
|
||||
static int num_attrs = 3;
|
||||
|
||||
string bus;
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < num_attrs; i++)
|
||||
{
|
||||
unsigned int val;
|
||||
int rc = HostSharePCI::get_pci_value(attrs[i].c_str(), pci, val);
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
error_str = "Wrong Hex value for PCI attribute " + attrs[i];
|
||||
return -1;
|
||||
}
|
||||
else if ( rc != 0 )
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
error_str = "DEVICE, VENDOR or CLASS must be defined for PCI.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( HostSharePCI::set_pci_address(pci, default_bus) != 0 )
|
||||
{
|
||||
error_str = "Wrong BUS in PCI attribute";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VirtualMachine::parse_pci(string& error_str)
|
||||
{
|
||||
vector<VectorAttribute *> array_pci;
|
||||
vector<VectorAttribute *>::iterator it;
|
||||
|
||||
int pci_id = 0;
|
||||
|
||||
user_obj_template->remove("PCI", array_pci);
|
||||
|
||||
for (it = array_pci.begin(); it !=array_pci.end(); ++it, ++pci_id)
|
||||
{
|
||||
(*it)->replace("PCI_ID", pci_id);
|
||||
|
||||
obj_template->set(*it);
|
||||
}
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
string default_bus;
|
||||
|
||||
nd.get_configuration_attribute("PCI_PASSTHROUGH_BUS", default_bus);
|
||||
|
||||
for (it = array_pci.begin(); it !=array_pci.end(); ++it)
|
||||
{
|
||||
if ( check_pci_attributes(*it, default_bus, error_str) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_graphics(string& error_str)
|
||||
{
|
||||
VectorAttribute * user_graphics = user_obj_template->get("GRAPHICS");
|
||||
|
||||
if ( user_graphics == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
VectorAttribute * graphics = new VectorAttribute(user_graphics);
|
||||
|
||||
user_obj_template->erase("GRAPHICS");
|
||||
|
||||
obj_template->set(graphics);
|
||||
|
||||
if ( !graphics->vector_value("PORT").empty() )
|
||||
{
|
||||
unsigned int port;
|
||||
|
||||
int rc = graphics->vector_value("PORT", port);
|
||||
|
||||
if (rc == -1 || port > 65535 )
|
||||
{
|
||||
error_str = "Wrong PORT number in GRAPHICS attribute";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
string random_passwd = graphics->vector_value("RANDOM_PASSWD");
|
||||
|
||||
if ( !random_passwd.empty() )
|
||||
{
|
||||
graphics->replace("PASSWD", one_util::random_password());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_requirements(string& error_str)
|
||||
{
|
||||
int rc, num;
|
||||
|
||||
vector<Attribute *> array_reqs;
|
||||
SingleAttribute * reqs;
|
||||
|
||||
string parsed;
|
||||
|
||||
num = user_obj_template->remove("SCHED_REQUIREMENTS", array_reqs);
|
||||
|
||||
if ( num == 0 ) // Compatibility with old REQUIREMENTS attribute
|
||||
{
|
||||
num = user_obj_template->remove("REQUIREMENTS", array_reqs);
|
||||
}
|
||||
else
|
||||
{
|
||||
user_obj_template->erase("REQUIREMENTS");
|
||||
}
|
||||
|
||||
if ( num == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ( num > 1 )
|
||||
{
|
||||
error_str = "Only one SCHED_REQUIREMENTS attribute can be defined.";
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
reqs = dynamic_cast<SingleAttribute *>(array_reqs[0]);
|
||||
|
||||
if ( reqs == 0 )
|
||||
{
|
||||
error_str = "Wrong format for SCHED_REQUIREMENTS attribute.";
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
rc = parse_template_attribute(reqs->value(), parsed, error_str);
|
||||
|
||||
if ( rc == 0 )
|
||||
{
|
||||
SingleAttribute * reqs_parsed;
|
||||
|
||||
reqs_parsed = new SingleAttribute("SCHED_REQUIREMENTS",parsed);
|
||||
user_obj_template->set(reqs_parsed);
|
||||
}
|
||||
|
||||
/* --- Delete old requirements attribute --- */
|
||||
|
||||
delete array_reqs[0];
|
||||
|
||||
return rc;
|
||||
|
||||
error_cleanup:
|
||||
for (int i = 0; i < num ; i++)
|
||||
{
|
||||
delete array_reqs[i];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void VirtualMachine::parse_well_known_attributes()
|
||||
{
|
||||
/*
|
||||
* List of meaningful attributes, used in other places and expected in
|
||||
* obj_template:
|
||||
*
|
||||
* DISK
|
||||
* NIC
|
||||
* VCPU
|
||||
* MEMORY
|
||||
* CPU
|
||||
* CONTEXT
|
||||
* OS
|
||||
* GRAPHICS
|
||||
*
|
||||
* INPUT
|
||||
* FEATURES
|
||||
* RAW
|
||||
* CLONING_TEMPLATE_ID
|
||||
*/
|
||||
|
||||
vector<Attribute *> v_attr;
|
||||
vector<Attribute *>::iterator it;
|
||||
|
||||
string names[] = {"INPUT", "FEATURES", "RAW", "CLONING_TEMPLATE_ID"};
|
||||
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
v_attr.clear();
|
||||
|
||||
user_obj_template->remove(names[i], v_attr);
|
||||
|
||||
for (it=v_attr.begin(); it != v_attr.end(); it++)
|
||||
{
|
||||
obj_template->set(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* VirtualMachine Lex & YACC parser functions */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
extern "C"
|
||||
{
|
||||
typedef struct yy_buffer_state * YY_BUFFER_STATE;
|
||||
|
||||
int vm_var_parse (VirtualMachine * vm,
|
||||
ostringstream * parsed,
|
||||
char ** errmsg);
|
||||
|
||||
int vm_file_var_parse (VirtualMachine * vm,
|
||||
vector<int> * img_ids,
|
||||
char ** errmsg);
|
||||
|
||||
int vm_var_lex_destroy();
|
||||
|
||||
YY_BUFFER_STATE vm_var__scan_string(const char * str);
|
||||
|
||||
void vm_var__delete_buffer(YY_BUFFER_STATE);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_template_attribute(const string& attribute,
|
||||
string& parsed,
|
||||
string& error_str)
|
||||
{
|
||||
YY_BUFFER_STATE str_buffer = 0;
|
||||
const char * str;
|
||||
int rc;
|
||||
ostringstream oss_parsed;
|
||||
char * error_msg = 0;
|
||||
|
||||
pthread_mutex_lock(&lex_mutex);
|
||||
|
||||
str = attribute.c_str();
|
||||
str_buffer = vm_var__scan_string(str);
|
||||
|
||||
if (str_buffer == 0)
|
||||
{
|
||||
goto error_yy;
|
||||
}
|
||||
|
||||
rc = vm_var_parse(this, &oss_parsed, &error_msg);
|
||||
|
||||
vm_var__delete_buffer(str_buffer);
|
||||
|
||||
vm_var_lex_destroy();
|
||||
|
||||
pthread_mutex_unlock(&lex_mutex);
|
||||
|
||||
if ( rc != 0 && error_msg != 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Error parsing: " << attribute << ". " << error_msg;
|
||||
log("VM", Log::ERROR, oss);
|
||||
|
||||
error_str = oss.str();
|
||||
|
||||
free(error_msg);
|
||||
}
|
||||
|
||||
parsed = oss_parsed.str();
|
||||
|
||||
return rc;
|
||||
|
||||
error_yy:
|
||||
log("VM",Log::ERROR,"Error setting scan buffer");
|
||||
pthread_mutex_unlock(&lex_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::parse_file_attribute(string attribute,
|
||||
vector<int>& img_ids,
|
||||
string& error)
|
||||
{
|
||||
YY_BUFFER_STATE str_buffer = 0;
|
||||
const char * str;
|
||||
int rc;
|
||||
ostringstream oss_parsed;
|
||||
char * error_msg = 0;
|
||||
|
||||
size_t non_blank_pos;
|
||||
|
||||
//Removes leading blanks from attribute, these are not managed
|
||||
//by the parser as it is common to the other VM varibales
|
||||
non_blank_pos = attribute.find_first_not_of(" \t\n\v\f\r");
|
||||
|
||||
if ( non_blank_pos != string::npos )
|
||||
{
|
||||
attribute.erase(0, non_blank_pos);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&lex_mutex);
|
||||
|
||||
str = attribute.c_str();
|
||||
str_buffer = vm_var__scan_string(str);
|
||||
|
||||
if (str_buffer == 0)
|
||||
{
|
||||
goto error_yy;
|
||||
}
|
||||
|
||||
rc = vm_file_var_parse(this, &img_ids, &error_msg);
|
||||
|
||||
vm_var__delete_buffer(str_buffer);
|
||||
|
||||
vm_var_lex_destroy();
|
||||
|
||||
pthread_mutex_unlock(&lex_mutex);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
if ( error_msg != 0 )
|
||||
{
|
||||
oss << "Error parsing: " << attribute << ". " << error_msg;
|
||||
free(error_msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "Unknown error parsing: " << attribute << ".";
|
||||
}
|
||||
|
||||
error = oss.str();
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
error_yy:
|
||||
log("VM",Log::ERROR,"Error setting scan buffer");
|
||||
pthread_mutex_unlock(&lex_mutex);
|
||||
return -1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user