1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-30 22:50:10 +03:00

Merge branch 'master' into remove-xen

This commit is contained in:
Jaime Melis 2016-04-06 18:20:47 +02:00
commit 0766d6a872
57 changed files with 1772 additions and 715 deletions

356
include/BitMap.h Normal file
View File

@ -0,0 +1,356 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, 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. */
/* -------------------------------------------------------------------------- */
#ifndef BITMAP_H_
#define BITMAP_H_
#include <bitset>
#include "Attribute.h"
#include "Callbackable.h"
class SqlDB;
/**
* This class represents a generic BitMap
*
*/
template <unsigned int N>
class BitMap : public Callbackable
{
public:
/**
* Creates a new bitmap, it stores a pointer to the DB parameters
* that MUST exists during the object lifetime.
*/
BitMap(const VectorAttribute& bs_conf, int _id, const char * _db_table)
: id(_id), start_bit(0), bs(0), db_table(_db_table)
{
std::string reserved;
bs_conf.vector_value("START", start_bit);
bs_conf.vector_value("RESERVED", reserved);
if (!reserved.empty())
{
one_util::split_unique(reserved, ',', reserved_bit);
}
};
virtual ~BitMap()
{
delete bs;
};
/* ---------------------------------------------------------------------- */
/* Database interface */
/* ---------------------------------------------------------------------- */
/**
* Returns a string stream with the SQL bootstrap command for the
* bitmap table
*/
static std::ostringstream& bootstrap(const char * t, std::ostringstream& o)
{
o << "CREATE TABLE IF NOT EXISTS " << t
<< " (id INTEGER, map LONGTEXT, PRIMARY KEY(id))";
return o;
}
/**
* Insert a new bitmap into the bitmap table. The bitmap marks the
* associated reserved bits as initialized by the bitmap conf. This
* function is called once to bootstrap the bitmap contents.
* @param id of the set, this will update the id of the bitmap
* @return 0 on success
*/
int insert(int _id, SqlDB * db)
{
id = _id;
init("");
return insert_replace(db, false);
}
/**
* Loads a bitmap and marks (again) the reserved bits. This function
* is called once to load the bitmap from the DB. The reserved bits are
* updated.
* @param id of the set, this will update the id of the bitmap
* @return 0 on success
*/
int select(int _id, SqlDB * db)
{
std::string * uzbs;
id = _id;
if ( select(db, &uzbs) != 0 )
{
return -1;
}
init(*uzbs);
delete uzbs;
return 0;
}
int update(SqlDB * db)
{
return insert_replace(db, true);
}
/**
* Deletes a bitmap from the DB.
* @return 0 on success
*/
int drop(SqlDB * db)
{
std::ostringstream oss;
oss << "DELETE FROM " << db_table << " WHERE id = " << id ;
return db->exec(oss);
}
/* ---------------------------------------------------------------------- */
/* BitMap interface */
/* ---------------------------------------------------------------------- */
/*+
* Gets the first 0 bit in the map and set it.
* @param hint try this bit first, 0 does not use any hint
* @param bit the bit number reserved
* @return -1 in case of error
*/
int get(unsigned int hint, unsigned int& bit)
{
if ( hint != 0 )
{
if ( bs->test(hint) == false )
{
bs->set(hint);
bit = hint;
return 0;
}
}
for (bit = start_bit; ; ++bit)
{
try
{
if ( bs->test(bit) == false )
{
bs->set(bit);
return 0;
}
}
catch (const std::out_of_range& oor)
{
return -1;
}
}
return -1;
}
/**
* Clears a bit in the map and updates DB.
* @param bit to reset
*/
void reset(int bit)
{
try
{
bs->reset(bit);
}
catch(const std::out_of_range& oor){};
}
/**
* Sets a bit in the map and updates DB.
* @param bit to set
* @return 0 on success, -1 if bit was set
*/
int set(int bit)
{
int rc = -1;
try
{
if (bs->test(bit) == false)
{
bs->set(bit);
rc = 0;
}
}
catch(const std::out_of_range& oor){};
return rc;
}
/**
* Return the start_bit of the bitmap
*/
unsigned int get_start_bit()
{
return start_bit;
}
private:
/* ---------------------------------------------------------------------- */
/* Bitmap configuration attributes */
/* ---------------------------------------------------------------------- */
int id;
unsigned int start_bit;
std::set<int> reserved_bit;
std::bitset<N> * bs;
/**
* Initialized a bitmap by creating a new object and setting the reserved
* bits.
* @param bm_s the bitmap in string form
*/
void init(const std::string& bm_s)
{
std::set<int>::iterator it;
bs = new std::bitset<N>(bm_s);
for (it = reserved_bit.begin(); it != reserved_bit.end(); ++it)
{
try
{
bs->set(*it);
}
catch (const std::out_of_range& oor) {};
}
}
/* ---------------------------------------------------------------------- */
/* Database implementation */
/* ---------------------------------------------------------------------- */
const char * db_table;
/**
* Select callback from DB engine
*/
int select_cb(void * _bs, int num, char **values, char **names)
{
if ( num == 0 || values == 0 || values[0] == 0 )
{
return -1;
}
*static_cast<std::string*>(_bs) = (const char *) values[0];
return 0;
}
/**
* Loads a the contents of a bitmap from DB
* @param **uzbs, pointer to a string pointer to store the bitmap, must
* be freed by caller.
* @return 0 on success
*/
int select(SqlDB * db, std::string ** uzbs)
{
int rc;
std::ostringstream oss;
std::string zbs;
*uzbs = 0;
set_callback(static_cast<Callbackable::Callback>(&BitMap::select_cb),
static_cast<void *>(&zbs));
oss << "SELECT map FROM " << db_table << " WHERE id = " << id ;
rc = db->exec(oss, this);
unset_callback();
if ( rc != 0 )
{
return rc;
}
else if (zbs.empty())
{
return -1;
}
*uzbs = one_util::zlib_decompress(zbs, true);
if ( *uzbs == 0 )
{
rc = -1;
}
return rc;
}
/**
* Insert a Bitmap in the DB, the bitmap is stored in a compressed (zlib)
* string form.
* @param replace true to replace false to insert
* @return 0 on success
*/
int insert_replace(SqlDB * db, bool replace)
{
std::ostringstream oss;
if (replace)
{
oss << "REPLACE ";
}
else
{
oss << "INSERT ";
}
std::string * zipped = one_util::zlib_compress(bs->to_string(), true);
if (zipped == 0)
{
return -1;
}
char * ezipped64 = db->escape_str(zipped->c_str());
oss << "INTO " << db_table << " (id, map) VALUES ("
<< id << ",'" << ezipped64 << "')";
int rc = db->exec(oss);
delete zipped;
db->free_str(ezipped64);
return rc;
}
};
#endif /*BITMAP_H_*/

View File

@ -21,6 +21,7 @@
#include "ObjectCollection.h"
#include "DatastorePool.h"
#include "ClusterTemplate.h"
#include "BitMap.h"
using namespace std;
@ -173,6 +174,36 @@ public:
get_template_attribute("RESERVED_MEM", mem);
}
// *************************************************************************
// VNC Port management function
// *************************************************************************
/**
* Returns a free VNC port, it will try first to allocate base_port + vmid.
* If this port is not free the first lower port from the VNC_PORT/START
* port is returned.
* @param vmid of the VM
* @param port reserved
* @return 0 on success
*/
int get_vnc_port(int vmid, unsigned int& port)
{
unsigned int base_port = vnc_bitmap.get_start_bit();
unsigned int hint_port = base_port + (vmid % (65535 - base_port));
return vnc_bitmap.get(hint_port,port);
}
void release_vnc_port(int port)
{
vnc_bitmap.reset(port);
}
int set_vnc_port(int port)
{
return vnc_bitmap.set(port);
}
// *************************************************************************
// DataBase implementation (Public)
// *************************************************************************
@ -203,9 +234,8 @@ private:
// *************************************************************************
// Constructor
// *************************************************************************
Cluster(int id,
const string& name,
ClusterTemplate* cl_template);
Cluster(int id, const string& name, ClusterTemplate* cl_template,
const VectorAttribute& vnc_conf);
virtual ~Cluster(){};
@ -216,6 +246,8 @@ private:
ObjectCollection datastores;
ObjectCollection vnets;
BitMap<65536> vnc_bitmap;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
@ -231,6 +263,7 @@ private:
static const char * network_db_names;
static const char * network_db_bootstrap;
static const char * bitmap_table;
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB
@ -268,7 +301,16 @@ private:
*/
int insert(SqlDB *db, string& error_str)
{
return insert_replace(db, false, error_str);
int rc;
rc = insert_replace(db, false, error_str);
if ( rc != 0 )
{
return rc;
}
return vnc_bitmap.insert(oid, db);
}
/**
@ -279,9 +321,48 @@ private:
int update(SqlDB *db)
{
string error_str;
return insert_replace(db, true, error_str);
int rc = insert_replace(db, true, error_str);
rc += vnc_bitmap.update(db);
return rc;
}
/**
* Reads the PoolObjectSQL (identified by its OID) from the database.
* @param db pointer to the db
* @return 0 on success
*/
int select(SqlDB *db)
{
int rc = PoolObjectSQL::select(db);
if ( rc != 0 )
{
return rc;
}
return vnc_bitmap.select(oid, db);
}
/**
* Reads the PoolObjectSQL (identified by its OID) from the database.
* @param db pointer to the db
* @return 0 on success
*/
int select(SqlDB *db, const string& _name, int _uid)
{
int rc = PoolObjectSQL::select(db, _name, _uid);
if ( rc != 0 )
{
return rc;
}
return vnc_bitmap.select(oid, db);
}
/**
* Checks if all the collections are empty, and therefore this cluster
* can be dropped.

View File

@ -26,7 +26,7 @@ using namespace std;
class ClusterPool : public PoolSQL
{
public:
ClusterPool(SqlDB * db);
ClusterPool(SqlDB * db, const VectorAttribute * vnc_conf);
~ClusterPool(){};
@ -54,6 +54,77 @@ public:
*/
static const int DEFAULT_CLUSTER_ID;
/* ---------------------------------------------------------------------- */
/* Cluster Resources */
/* ---------------------------------------------------------------------- */
/**
* Get a free VNC port in the cluster. It will try first base_port + id
* @param oid of the cluster
* @param vm_id of the ID requesting the port
* @param port to free
*/
int get_vnc_port(int oid, int vm_id, unsigned int& port)
{
int rc = -1;
Cluster * cluster = get(oid, true);
if ( cluster != 0 )
{
rc = cluster->get_vnc_port(vm_id, port);
update(cluster);
cluster->unlock();
}
return rc;
};
/**
* Release a previously allocated VNC port in the cluster
* @param oid of the cluster
* @param port to free
*/
void release_vnc_port(int oid, unsigned int port)
{
Cluster * cluster = get(oid, true);
if ( cluster != 0 )
{
cluster->release_vnc_port(port);
update(cluster);
cluster->unlock();
}
}
/**
* Mark a VNC port as in-use in the cluster.
* @param oid of the cluster
* @param port to set
*
* @return 0 on success, -1 if the port was in-use.
*/
int set_vnc_port(int oid, unsigned int port)
{
int rc = -1;
Cluster * cluster = get(oid, true);
if ( cluster != 0 )
{
rc = cluster->set_vnc_port(port);
update(cluster);
cluster->unlock();
}
return rc;
}
/* ---------------------------------------------------------------------- */
/* Methods for DB management */
/* ---------------------------------------------------------------------- */
@ -67,9 +138,7 @@ public:
*
* @return the oid assigned to the object, -1 in case of failure
*/
int allocate(string name,
int * oid,
string& error_str);
int allocate(string name, int * oid, string& error_str);
/**
* Function to get a cluster from the pool, if the object is not in memory
@ -128,7 +197,13 @@ public:
*/
static int bootstrap(SqlDB * _db)
{
return Cluster::bootstrap(_db);
ostringstream oss_bitmap;
int rc;
rc = Cluster::bootstrap(_db);
rc += _db->exec(BitMap<0>::bootstrap(Cluster::bitmap_table, oss_bitmap));
return rc;
};
/**
@ -156,13 +231,18 @@ public:
static void cluster_acl_filter(ostringstream& filter,
PoolObjectSQL::ObjectType auth_object, const vector<int>& cids);
private:
/**
* VNC configuration for clusters
*/
const VectorAttribute vnc_conf;
/**
* Factory method to produce objects
* @return a pointer to the new object
*/
PoolObjectSQL * create()
{
return new Cluster(-1,"",0);
return new Cluster(-1,"",0, &vnc_conf);
};
};

View File

@ -22,6 +22,7 @@
#include "HostPool.h"
#include "ImagePool.h"
#include "SecurityGroupPool.h"
#include "ClusterPool.h"
using namespace std;
@ -42,7 +43,8 @@ class LifeCycleManager : public ActionListener
public:
LifeCycleManager():
vmpool(0), hpool(0), ipool(0), sgpool(0), tm(0), vmm(0), dm(0), imagem(0)
vmpool(0), hpool(0), ipool(0), sgpool(0), clpool(0), tm(0), vmm(0),
dm(0), imagem(0)
{
am.addListener(this);
};
@ -178,6 +180,11 @@ private:
*/
SecurityGroupPool * sgpool;
/**
* Pointer to the Cluster Pool
*/
ClusterPool * clpool;
/**
* Pointer to TransferManager
*/

View File

@ -238,6 +238,24 @@ namespace one_util
return output;
}
/**
* Compress the input string unsing zlib
* @param in input string
* @param bool64 true to base64 encode output
* @return pointer to the compressed sting (must be freed) or 0 in case
* of error
*/
std::string * zlib_compress(const std::string& in, bool base64);
/**
* Decompress the input string unsing zlib
* @param in input string
* @param base64 true if the input is base64 encoded
* @return pointer to the decompressed sting (must be freed) or 0 in case
* of error
*/
std::string * zlib_decompress(const std::string& in, bool base64);
};
#endif /* _NEBULA_UTIL_H_ */

View File

@ -1439,22 +1439,6 @@ public:
*/
static void disk_extended_info(int uid,
VirtualMachineTemplate *tmpl);
/**
* Adds extra info to the volatile disks of the given template, ds inherited
* attributes and TYPE
* @param tmpl the virtual machine template
* @return true if there at least one volatile disk was found
*/
bool volatile_disk_extended_info(Template *tmpl);
/**
* Adds extra info to the volatile disks of the given VM
*/
bool volatile_disk_extended_info()
{
return volatile_disk_extended_info(obj_template);
}
// -------------------------------------------------------------------------
// Hotplug related functions
// -------------------------------------------------------------------------
@ -1465,14 +1449,6 @@ public:
*/
void get_disk_info(int& max_disk_id, set<string>& used_targets);
/**
* Get the IMAGE_ID of the image that's being saved as hot
* @param disk_id of the DISK
* @param image_id id of the image being saved
* @return IMAGE_ID on success, -1 otherwise
*/
//int get_disk_hot_info(int& image_id, int& disk_id, string& source);
/**
* Generate a DISK attribute to be attached to the VM.
* @param tmpl Template containing a single DISK vector attribute.

View File

@ -24,7 +24,6 @@
using namespace std;
/**
* The Virtual Machine Pool class. ...
*/
@ -393,19 +392,19 @@ private:
/**
* Size, in seconds, of the historical monitoring information
*/
static time_t _monitor_expiration;
time_t _monitor_expiration;
/**
* True or false whether to submit new VM on HOLD or not
*/
static bool _submit_on_hold;
bool _submit_on_hold;
/**
* Default values for cpu and memory cost
*/
static float _default_cpu_cost;
static float _default_mem_cost;
static float _default_disk_cost;
float _default_cpu_cost;
float _default_mem_cost;
float _default_disk_cost;
/**
* Callback used to get an int in the DB it is used by VM Pool in:

View File

@ -34,8 +34,9 @@
# passwd : (mysql) the password for user
# db_name : (mysql) the database name
#
# VNC_BASE_PORT: VNC ports for VMs can be automatically set to VNC_BASE_PORT +
# VMID
# VNC_PORTS: VNC port pool fot automatic VNC port assigment
# start : first port to assgin
# reserved: comma separated list of ports
#
# LOG: Configuration for the logging system
# system: defines the logging system:
@ -77,7 +78,10 @@ DB = [ backend = "sqlite" ]
# passwd = "oneadmin",
# db_name = "opennebula" ]
VNC_BASE_PORT = 5900
VNC_PORTS = [
start = 5900
# reserved = "6800, 6801, 9869"
]
#VM_SUBMIT_ON_HOLD = "NO"
@ -88,19 +92,19 @@ VNC_BASE_PORT = 5900
# requires a special DB configuration.
#
# FEDERATION: Federation attributes
# MODE: Operation mode of this oned.
# mode: Operation mode of this oned.
# STANDALONE no federated.This is the default operational mode
# MASTER this oned is the master zone of the federation
# SLAVE this oned is a slave zone
# ZONE_ID: The zone ID as returned by onezone command
# MASTER_ONED: The xml-rpc endpoint of the master oned, e.g.
# zone_id: The zone ID as returned by onezone command
# master_oned: The xml-rpc endpoint of the master oned, e.g.
# http://master.one.org:2633/RPC2
#*******************************************************************************
FEDERATION = [
MODE = "STANDALONE",
ZONE_ID = 0,
MASTER_ONED = ""
mode = "STANDALONE",
zone_id = 0,
master_oned = ""
]
#*******************************************************************************

View File

@ -39,8 +39,10 @@
# passwd : (mysql) the password for user
# db_name : (mysql) the database name
#
# VNC_BASE_PORT: VNC ports for VMs can be automatically set to VNC_BASE_PORT +
# VMID
# VNC_PORTS: VNC port pool fot automatic VNC port assigment, if possible the
# port will be set to ``START`` + ``VMID``
# start : first port to assgin
# reserved: comma separated list of ports
#
# LOG: Configuration for the logging system
# system: defines the logging system:
@ -86,7 +88,10 @@ DB = [ backend = "sqlite" ]
# passwd = "oneadmin",
# db_name = "opennebula" ]
VNC_BASE_PORT = 5900
VNC_PORTS = [
start = 5900
# reserved = "6800, 6801, 9869"
]
#VM_SUBMIT_ON_HOLD = "NO"
@ -107,9 +112,9 @@ VNC_BASE_PORT = 5900
#*******************************************************************************
FEDERATION = [
MODE = "STANDALONE",
ZONE_ID = 0,
MASTER_ONED = ""
mode = "STANDALONE",
zone_id = 0,
master_oned = ""
]
#*******************************************************************************
@ -959,7 +964,8 @@ TM_MAD_CONF = [
DS_MAD_CONF = [
NAME = "ceph",
REQUIRED_ATTRS = "DISK_TYPE,BRIDGE_LIST,CEPH_HOST,CEPH_USER,CEPH_SECRET",
PERSISTENT_ONLY = "NO"
PERSISTENT_ONLY = "NO",
MARKETPLACE_ACTIONS = "export"
]
DS_MAD_CONF = [
@ -976,7 +982,8 @@ DS_MAD_CONF = [
]
DS_MAD_CONF = [
NAME = "fs", REQUIRED_ATTRS = "", PERSISTENT_ONLY = "NO"
NAME = "fs", REQUIRED_ATTRS = "", PERSISTENT_ONLY = "NO",
MARKETPLACE_ACTIONS = "export"
]
DS_MAD_CONF = [
@ -997,7 +1004,8 @@ DS_MAD_CONF = [
]
DS_MAD_CONF = [
NAME = "vcenter", REQUIRED_ATTRS = "VCENTER_CLUSTER", PERSISTENT_ONLY = "YES"
NAME = "vcenter", REQUIRED_ATTRS = "VCENTER_CLUSTER", PERSISTENT_ONLY = "YES",
MARKETPLACE_ACTIONS = "export"
]
#*******************************************************************************

View File

@ -258,7 +258,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
answer = STDIN.gets.strip
t[:one] += "VCENTER_DATASTORE=#{answer}"
t[:one] += "VCENTER_DATASTORE=\"#{answer}\"\n"
end
# Resource Pools
@ -267,7 +267,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
if rp_split.size > 3
STDOUT.print "\n This template is currently set to "\
"launch VMs in the default resource pool."
"launch VMs in the default resource pool."\
"\n Press y to keep this behaviour, n to select"\
" a new resource pool or d to delegate the choice"\
" to the user [y/n/d]? "
@ -324,7 +324,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
answer = STDIN.gets.strip
t[:one] += "RESOURCE_POOL=#{answer}"
t[:one] += "RESOURCE_POOL=\"#{answer}\"\n"
end
end

View File

@ -46,6 +46,8 @@ const char * Cluster::network_db_bootstrap =
"CREATE TABLE IF NOT EXISTS cluster_network_relation ("
"cid INTEGER, oid INTEGER, PRIMARY KEY(cid, oid))";
const char * Cluster::bitmap_table = "vm_bitmap";
/* ************************************************************************** */
/* Cluster :: Constructor/Destructor */
/* ************************************************************************** */
@ -53,11 +55,13 @@ const char * Cluster::network_db_bootstrap =
Cluster::Cluster(
int id,
const string& name,
ClusterTemplate* cl_template):
ClusterTemplate* cl_template,
const VectorAttribute& vnc_conf):
PoolObjectSQL(id,CLUSTER,name,-1,-1,"","",table),
hosts("HOSTS"),
datastores("DATASTORES"),
vnets("VNETS")
vnets("VNETS"),
vnc_bitmap(vnc_conf, id, bitmap_table)
{
if (cl_template != 0)
{
@ -68,11 +72,8 @@ Cluster::Cluster(
obj_template = new ClusterTemplate;
}
string default_cpu; //TODO - Get these two from oned.conf
string default_mem;
add_template_attribute("RESERVED_CPU", default_cpu);
add_template_attribute("RESERVED_MEM", default_cpu);
add_template_attribute("RESERVED_CPU", "");
add_template_attribute("RESERVED_MEM", "");
}
/* -------------------------------------------------------------------------- */
@ -225,7 +226,6 @@ int Cluster::insert_replace(SqlDB *db, bool replace, string& error_str)
}
// Construct the SQL statement to Insert or Replace
oss <<" INTO "<<table <<" ("<< db_names <<") VALUES ("
<< oid << ","
<< "'" << sql_name << "',"
@ -302,9 +302,9 @@ int Cluster::insert_replace(SqlDB *db, bool replace, string& error_str)
{
oss.str("");
oss << "BEGIN; "
<< "DELETE FROM " << network_table << " WHERE cid = " << oid << "; "
<< "DELETE FROM " << datastore_table<< " WHERE cid = " << oid << "; ";
oss <<"BEGIN; "
<<"DELETE FROM "<< network_table <<" WHERE cid = "<< oid<< "; "
<<"DELETE FROM "<< datastore_table<<" WHERE cid = "<< oid<< "; ";
set<int>::iterator i;

View File

@ -35,7 +35,8 @@ const int ClusterPool::DEFAULT_CLUSTER_ID = 0;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table, true, true)
ClusterPool::ClusterPool(SqlDB * db, const VectorAttribute * _vnc_conf):
PoolSQL(db, Cluster::table, true, true), vnc_conf(_vnc_conf)
{
ostringstream oss;
string error_str;
@ -109,7 +110,7 @@ int ClusterPool::allocate(string name, int * oid, string& error_str)
}
// Build a new Cluster object
cluster = new Cluster(-1, name, 0);
cluster = new Cluster(-1, name, 0, vnc_conf);
// Insert the Object in the pool
*oid = PoolSQL::allocate(cluster, error_str);

View File

@ -23,6 +23,8 @@
#include <openssl/buffer.h>
#include <openssl/aes.h>
#include <zlib.h>
#include <string>
#include <sstream>
#include <cstring>
@ -333,3 +335,148 @@ std::string one_util::gsub(const std::string& st, const std::string& sfind,
return result;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* Buffer length for zlib inflate/deflate
*/
#define ZBUFFER 16384
std::string * one_util::zlib_compress(const std::string& in, bool base64)
{
z_stream zs;
std::ostringstream oss;
unsigned char out[ZBUFFER];
std::string * zstr;
if ( in.empty() )
{
return 0;
}
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
if ( deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK )
{
return 0;
}
zs.avail_in = in.size();
zs.next_in = (unsigned char *) const_cast<char *>(in.c_str());
do
{
zs.avail_out = ZBUFFER;
zs.next_out = out;
if ( deflate(&zs, Z_FINISH) == Z_STREAM_ERROR )
{
deflateEnd(&zs);
return 0;
}
oss.write((const char *)out, ZBUFFER - zs.avail_out);
} while (zs.avail_out == 0);
deflateEnd(&zs);
if ( base64 )
{
zstr = one_util::base64_encode(oss.str());
}
else
{
zstr = new std::string(oss.str());
}
return zstr;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
std::string * one_util::zlib_decompress(const std::string& in, bool base64)
{
int rc;
z_stream zs;
std::ostringstream oss;
unsigned char out[ZBUFFER];
std::string * in64;
if ( in.empty() )
{
return 0;
}
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.avail_in = 0;
zs.next_in = Z_NULL;
if ( inflateInit(&zs) != Z_OK)
{
return 0;
}
if ( base64 )
{
in64 = one_util::base64_decode(in);
if (in64 == 0)
{
inflateEnd(&zs);
return 0;
}
zs.avail_in = in64->size();
zs.next_in = (unsigned char *) const_cast<char *>(in64->c_str());
}
else
{
zs.avail_in = in.size();
zs.next_in = (unsigned char *) const_cast<char *>(in.c_str());
}
do
{
zs.avail_out = ZBUFFER;
zs.next_out = out;
if ( (rc = inflate(&zs, Z_FINISH)) == Z_STREAM_ERROR )
{
inflateEnd(&zs);
if ( base64 )
{
delete in64;
}
return 0;
}
oss.write((const char *)out, ZBUFFER - zs.avail_out);
} while (rc != Z_STREAM_END);
inflateEnd(&zs);
if ( base64 )
{
delete in64;
}
return new std::string(oss.str());
}

View File

@ -835,6 +835,8 @@ void LifeCycleManager::clean_action(int vid)
void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& image_id)
{
int cpu, mem, disk;
unsigned int port;
vector<VectorAttribute *> pci;
time_t the_time = time(0);
@ -865,8 +867,16 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag
vm->set_reason(History::USER);
vm->get_requirements(cpu, mem, disk, pci);
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
const VectorAttribute * graphics = vm->get_template_attribute("GRAPHICS");
if ( graphics != 0 && (graphics->vector_value("PORT", port) == 0))
{
clpool->release_vnc_port(vm->get_cid(), port);
}
switch (state)
{
case VirtualMachine::PROLOG:

View File

@ -74,6 +74,7 @@ void LifeCycleManager::init_managers()
hpool = nd.get_hpool();
ipool = nd.get_ipool();
sgpool = nd.get_secgrouppool();
clpool = nd.get_clpool();
}
/* -------------------------------------------------------------------------- */

View File

@ -811,6 +811,7 @@ void LifeCycleManager::epilog_success_action(int vid)
time_t the_time = time(0);
int cpu,mem,disk;
unsigned int port;
VirtualMachine::LcmState state;
DispatchManager::Actions action;
@ -883,6 +884,13 @@ void LifeCycleManager::epilog_success_action(int vid)
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
const VectorAttribute * graphics = vm->get_template_attribute("GRAPHICS");
if ( graphics != 0 && (graphics->vector_value("PORT", port) == 0))
{
clpool->release_vnc_port(vm->get_cid(), port);
}
//----------------------------------------------------
dm->trigger(action,vid);

View File

@ -436,170 +436,160 @@ void Nebula::start(bool bootstrap_only)
throw runtime_error("Could not start the ACL Manager");
}
// -----------------------------------------------------------
// -------------------------------------------------------------------------
// Pools
// -----------------------------------------------------------
// -------------------------------------------------------------------------
try
{
int size;
/* -------------------------- Cluster Pool -------------------------- */
const VectorAttribute * vnc_conf;
string mac_prefix;
string default_image_type;
string default_device_prefix;
string default_cdrom_device_prefix;
vnc_conf = nebula_configuration->get("VNC_PORTS");
time_t expiration_time;
time_t vm_expiration;
time_t host_expiration;
bool vm_submit_on_hold;
float cpu_cost;
float mem_cost;
float disk_cost;
clpool = new ClusterPool(db, vnc_conf);
/* --------------------- VirtualMachine Pool ------------------------ */
vector<const VectorAttribute *> vm_hooks;
vector<const VectorAttribute *> host_hooks;
vector<const VectorAttribute *> vrouter_hooks;
vector<const VectorAttribute *> vnet_hooks;
vector<const VectorAttribute *> user_hooks;
vector<const VectorAttribute *> group_hooks;
vector<const VectorAttribute *> image_hooks;
vector<const SingleAttribute *> vm_restricted_attrs;
vector<const SingleAttribute *> img_restricted_attrs;
vector<const SingleAttribute *> vnet_restricted_attrs;
vector<const SingleAttribute *> inherit_image_attrs;
vector<const SingleAttribute *> inherit_datastore_attrs;
vector<const SingleAttribute *> inherit_vnet_attrs;
time_t vm_expiration;
bool vm_submit_on_hold;
vector<const VectorAttribute *> default_cost;
float cpu_cost;
float mem_cost;
float disk_cost;
clpool = new ClusterPool(db);
docpool = new DocumentPool(db);
zonepool= new ZonePool(db, is_federation_slave());
vdcpool = new VdcPool(db, is_federation_slave());
const VectorAttribute * default_cost;
nebula_configuration->get("VM_HOOK", vm_hooks);
nebula_configuration->get("HOST_HOOK", host_hooks);
nebula_configuration->get("VROUTER_HOOK", vrouter_hooks);
nebula_configuration->get("VNET_HOOK", vnet_hooks);
nebula_configuration->get("USER_HOOK", user_hooks);
nebula_configuration->get("GROUP_HOOK", group_hooks);
nebula_configuration->get("IMAGE_HOOK", image_hooks);
nebula_configuration->get("VM_HOOK", vm_hooks);
nebula_configuration->get("VM_RESTRICTED_ATTR", vm_restricted_attrs);
nebula_configuration->get("IMAGE_RESTRICTED_ATTR", img_restricted_attrs);
nebula_configuration->get("VNET_RESTRICTED_ATTR", vnet_restricted_attrs);
nebula_configuration->get("INHERIT_IMAGE_ATTR", inherit_image_attrs);
nebula_configuration->get("INHERIT_DATASTORE_ATTR", inherit_datastore_attrs);
nebula_configuration->get("INHERIT_VNET_ATTR", inherit_vnet_attrs);
nebula_configuration->get("VM_MONITORING_EXPIRATION_TIME",vm_expiration);
nebula_configuration->get("HOST_MONITORING_EXPIRATION_TIME",host_expiration);
nebula_configuration->get("VM_SUBMIT_ON_HOLD",vm_submit_on_hold);
rc = nebula_configuration->get("DEFAULT_COST", default_cost);
default_cost = nebula_configuration->get("DEFAULT_COST");
cpu_cost = 0;
mem_cost = 0;
disk_cost= 0;
if (rc != 0)
if (default_cost->vector_value("CPU_COST", cpu_cost) != 0)
{
const VectorAttribute * vatt = static_cast<const VectorAttribute *>
(default_cost[0]);
rc = vatt->vector_value("CPU_COST", cpu_cost);
if (rc != 0)
{
cpu_cost = 0;
}
rc = vatt->vector_value("MEMORY_COST", mem_cost);
if (rc != 0)
{
mem_cost = 0;
}
rc = vatt->vector_value("DISK_COST", disk_cost);
if (rc != 0)
{
disk_cost = 0;
}
cpu_cost = 0;
}
vmpool = new VirtualMachinePool(db,
vm_hooks,
hook_location,
remotes_location,
vm_restricted_attrs,
vm_expiration,
vm_submit_on_hold,
cpu_cost,
mem_cost,
disk_cost);
if (default_cost->vector_value("MEMORY_COST", mem_cost) != 0)
{
mem_cost = 0;
}
hpool = new HostPool(db,
host_hooks,
hook_location,
remotes_location,
host_expiration);
if (default_cost->vector_value("DISK_COST", disk_cost) != 0)
{
disk_cost = 0;
}
vrouterpool = new VirtualRouterPool(db,
vrouter_hooks,
remotes_location);
vmpool = new VirtualMachinePool(db, vm_hooks, hook_location,
remotes_location, vm_restricted_attrs, vm_expiration,
vm_submit_on_hold, cpu_cost, mem_cost, disk_cost);
/* ---------------------------- Host Pool --------------------------- */
vector<const VectorAttribute *> host_hooks;
time_t host_expiration;
nebula_configuration->get("HOST_HOOK", host_hooks);
nebula_configuration->get("HOST_MONITORING_EXPIRATION_TIME", host_expiration);
hpool = new HostPool(db, host_hooks, hook_location, remotes_location,
host_expiration);
/* --------------------- VirtualRouter Pool ------------------------- */
vector<const VectorAttribute *> vrouter_hooks;
nebula_configuration->get("VROUTER_HOOK", vrouter_hooks);
vrouterpool = new VirtualRouterPool(db, vrouter_hooks, remotes_location);
/* -------------------- VirtualNetwork Pool ------------------------- */
int size;
string mac_prefix;
vector<const SingleAttribute *> inherit_vnet_attrs;
vector<const SingleAttribute *> vnet_restricted_attrs;
vector<const VectorAttribute *> vnet_hooks;
nebula_configuration->get("MAC_PREFIX", mac_prefix);
nebula_configuration->get("NETWORK_SIZE", size);
vnpool = new VirtualNetworkPool(db,
mac_prefix,
size,
vnet_restricted_attrs,
vnet_hooks,
remotes_location,
inherit_vnet_attrs);
nebula_configuration->get("VNET_RESTRICTED_ATTR", vnet_restricted_attrs);
gpool = new GroupPool(db, group_hooks,
remotes_location, is_federation_slave());
nebula_configuration->get("VNET_HOOK", vnet_hooks);
nebula_configuration->get("INHERIT_VNET_ATTR", inherit_vnet_attrs);
vnpool = new VirtualNetworkPool(db, mac_prefix, size, vnet_restricted_attrs,
vnet_hooks, remotes_location, inherit_vnet_attrs);
/* ----------------------- Group/User Pool -------------------------- */
vector<const VectorAttribute *> user_hooks;
vector<const VectorAttribute *> group_hooks;
time_t expiration_time;
nebula_configuration->get("GROUP_HOOK", group_hooks);
gpool = new GroupPool(db, group_hooks, remotes_location,
is_federation_slave());
nebula_configuration->get("SESSION_EXPIRATION_TIME", expiration_time);
upool = new UserPool(db, expiration_time, user_hooks,
remotes_location, is_federation_slave());
nebula_configuration->get("USER_HOOK", user_hooks);
nebula_configuration->get("DEFAULT_IMAGE_TYPE", default_image_type);
nebula_configuration->get("DEFAULT_DEVICE_PREFIX",
default_device_prefix);
nebula_configuration->get("DEFAULT_CDROM_DEVICE_PREFIX",
default_cdrom_device_prefix);
ipool = new ImagePool(db,
default_image_type,
default_device_prefix,
default_cdrom_device_prefix,
img_restricted_attrs,
image_hooks,
remotes_location,
inherit_image_attrs);
upool = new UserPool(db, expiration_time, user_hooks, remotes_location,
is_federation_slave());
tpool = new VMTemplatePool(db);
/* -------------------- Image/Datastore Pool ------------------------ */
string image_type;
string device_prefix;
string cd_dev_prefix;
dspool = new DatastorePool(db, inherit_datastore_attrs);
vector<const VectorAttribute *> image_hooks;
vector<const SingleAttribute *> img_restricted_attrs;
vector<const SingleAttribute *> inherit_image_attrs;
vector<const SingleAttribute *> inherit_ds_attrs;
default_user_quota.select();
default_group_quota.select();
nebula_configuration->get("DEFAULT_IMAGE_TYPE", image_type);
nebula_configuration->get("DEFAULT_DEVICE_PREFIX", device_prefix);
nebula_configuration->get("DEFAULT_CDROM_DEVICE_PREFIX", cd_dev_prefix);
nebula_configuration->get("IMAGE_HOOK", image_hooks);
nebula_configuration->get("IMAGE_RESTRICTED_ATTR", img_restricted_attrs);
nebula_configuration->get("INHERIT_IMAGE_ATTR", inherit_image_attrs);
ipool = new ImagePool(db, image_type, device_prefix, cd_dev_prefix,
img_restricted_attrs, image_hooks, remotes_location,
inherit_image_attrs);
nebula_configuration->get("INHERIT_DATASTORE_ATTR", inherit_ds_attrs);
dspool = new DatastorePool(db, inherit_ds_attrs);
/* ----- Document, Zone, VDC, VMTemplate, SG and Makerket Pools ----- */
docpool = new DocumentPool(db);
zonepool = new ZonePool(db, is_federation_slave());
vdcpool = new VdcPool(db, is_federation_slave());
tpool = new VMTemplatePool(db);
secgrouppool = new SecurityGroupPool(db);
marketpool = new MarketPlacePool(db, is_federation_slave());
apppool = new MarketPlaceAppPool(db, is_federation_slave());
marketpool = new MarketPlacePool(db, is_federation_slave());
apppool = new MarketPlaceAppPool(db, is_federation_slave());
default_user_quota.select();
default_group_quota.select();
}
catch (exception&)
{

View File

@ -310,9 +310,9 @@ void OpenNebulaTemplate::set_conf_default()
# LISTEN_ADDRESS
# PORT
# DB
# VNC_BASE_PORT
# SCRIPTS_REMOTE_DIR
# VM_SUBMIT_ON_HOLD
# VNC_PORTS
#*******************************************************************************
*/
set_conf_single("MANAGER_TIMER", "15");
@ -325,7 +325,6 @@ void OpenNebulaTemplate::set_conf_default()
set_conf_single("VM_MONITORING_EXPIRATION_TIME", "14400");
set_conf_single("PORT", "2633");
set_conf_single("LISTEN_ADDRESS", "0.0.0.0");
set_conf_single("VNC_BASE_PORT", "5900");
set_conf_single("SCRIPTS_REMOTE_DIR", "/var/tmp/one");
set_conf_single("VM_SUBMIT_ON_HOLD", "NO");
@ -342,6 +341,15 @@ void OpenNebulaTemplate::set_conf_default()
vattribute = new VectorAttribute("LOG",vvalue);
conf_default.insert(make_pair(vattribute->name(),vattribute));
// LOG CONFIGURATION
vvalue.clear();
vvalue.insert(make_pair("RESERVED",""));
vvalue.insert(make_pair("START","5900"));
vattribute = new VectorAttribute("VNC_PORTS",vvalue);
conf_default.insert(make_pair(vattribute->name(),vattribute));
/*
#*******************************************************************************
# Federation configuration attributes

View File

@ -446,15 +446,13 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm,
RequestAttributes& att)
{
string vmdir;
int rc;
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
vm->add_history(hid, cid, hostname, vmm_mad, vnm_mad, tm_mad, ds_location, ds_id);
vm->add_history(hid, cid, hostname, vmm_mad, vnm_mad, tm_mad, ds_location,
ds_id);
rc = vmpool->update_history(vm);
if ( rc != 0 )
if ( vmpool->update_history(vm) != 0 )
{
att.resp_msg = "Cannot update virtual machine history";
failure_response(INTERNAL, att);
@ -462,7 +460,13 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm,
return -1;
}
vmpool->update(vm);
if ( vmpool->update(vm) != 0 )
{
att.resp_msg = "Cannot update virtual machine";
failure_response(INTERNAL, att);
return -1;
}
return 0;
}
@ -650,6 +654,127 @@ void VirtualMachineAction::request_execute(xmlrpc_c::paramList const& paramList,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* Adds extra info to the volatile disks of the given template, ds inherited
* attributes and TYPE
* @param ds_id datastore id
* @param vd vector of DISKS
* @return true if there at least one volatile disk was found
*/
static bool set_volatile_disk_info(int ds_id, vector<VectorAttribute *>& vd)
{
DatastorePool * ds_pool = Nebula::instance().get_dspool();
bool found = false;
for(vector<VectorAttribute *>::iterator it = vd.begin(); it!=vd.end(); ++it)
{
if ( !VirtualMachine::is_volatile(*it) )
{
continue;
}
ds_pool->disk_attribute(ds_id, *it);
found = true;
}
return found;
}
static bool set_volatile_disk_info(VirtualMachine *vm)
{
if ( !vm->hasHistory() )
{
return false;
}
vector<VectorAttribute *> disks;
int ds_id = vm->get_ds_id();
vm->get_template_attribute("DISK", disks);
bool found = set_volatile_disk_info(ds_id, disks);
if ( found )
{
Nebula::instance().get_vmpool()->update(vm);
}
return found;
}
static bool set_volatile_disk_info(VirtualMachine *vm, Template& tmpl)
{
if ( !vm->hasHistory() )
{
return false;
}
vector<VectorAttribute *> disks;
int ds_id = vm->get_ds_id();
tmpl.get("DISK", disks);
bool found = set_volatile_disk_info(ds_id, disks);
if ( found )
{
Nebula::instance().get_vmpool()->update(vm);
}
return found;
}
/* -------------------------------------------------------------------------- */
int set_vnc_port(VirtualMachine *vm, RequestAttributes& att)
{
ClusterPool * cpool = Nebula::instance().get_clpool();
VectorAttribute * graphics = vm->get_template_attribute("GRAPHICS");
unsigned int port;
int rc;
if (graphics == 0 || !vm->hasHistory())
{
return 0;
}
else if (graphics->vector_value("PORT", port) == 0)
{
rc = cpool->set_vnc_port(vm->get_cid(), port);
if ( rc != 0 )
{
att.resp_msg = "Requested VNC port already assgined to a VM";
}
}
else
{
rc = cpool->get_vnc_port(vm->get_cid(), vm->get_oid(), port);
if ( rc == 0 )
{
graphics->replace("PORT", port);
Nebula::instance().get_vmpool()->update(vm);
}
else
{
att.resp_msg = "No free VNC ports available in the cluster";
}
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
@ -743,7 +868,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
set<int> ds_cluster_ids;
bool ds_migr;
if (get_ds_information(ds_id, ds_cluster_ids, tm_mad, att, ds_migr) != 0)
if (get_ds_information(ds_id,ds_cluster_ids,tm_mad,att,ds_migr) != 0)
{
return;
}
@ -752,10 +877,11 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
{
ostringstream oss;
oss << object_name(PoolObjectSQL::DATASTORE) << " [" << ds_id << "] and "
<< object_name(PoolObjectSQL::HOST) << " [" << hid
<< "] are not in the same "
<< object_name(PoolObjectSQL::CLUSTER) << " [" << cluster_id << "].";
oss << object_name(PoolObjectSQL::DATASTORE) << " [" << ds_id
<< "] and " << object_name(PoolObjectSQL::HOST) << " ["
<< hid << "] are not in the same "
<< object_name(PoolObjectSQL::CLUSTER) << " [" << cluster_id
<< "].";
att.resp_msg = oss.str();
@ -806,7 +932,6 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
// - VM States are right
// - Host capacity if required
// ------------------------------------------------------------------------
if ((vm = get_vm(id, att)) == 0)
{
return;
@ -817,7 +942,9 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
vm->get_state() != VirtualMachine::STOPPED &&
vm->get_state() != VirtualMachine::UNDEPLOYED)
{
att.resp_msg = "Deploy action is not available for state " + vm->state_str();
att.resp_msg = "Deploy action is not available for state " +
vm->state_str();
failure_response(ACTION, att);
vm->unlock();
@ -833,9 +960,8 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
}
// ------------------------------------------------------------------------
// Add a new history record and update volatile DISK info
// Add a new history record
// ------------------------------------------------------------------------
if (add_history(vm,
hid,
cluster_id,
@ -851,7 +977,19 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
return;
}
vm->volatile_disk_extended_info();
// ------------------------------------------------------------------------
// Add deployment dependent attributes to VM
// - volatile disk (selected system DS driver)
// - vnc port (free in the selected cluster)
// ------------------------------------------------------------------------
set_volatile_disk_info(vm);
if (set_vnc_port(vm, att) != 0)
{
failure_response(ACTION, att);
vm->unlock();
return;
}
// ------------------------------------------------------------------------
// deploy the VM
@ -1178,7 +1316,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
vm->volatile_disk_extended_info();
set_volatile_disk_info(vm);
// ------------------------------------------------------------------------
// Migrate the VM
@ -1570,9 +1708,10 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
vm->get_permissions(vm_perms);
volatile_disk = vm->volatile_disk_extended_info(&tmpl);
volatile_disk = set_volatile_disk_info(vm, tmpl);
if (vm->is_vrouter() && !VirtualRouter::is_action_supported(History::DISK_ATTACH_ACTION))
if (vm->is_vrouter() &&
!VirtualRouter::is_action_supported(History::DISK_ATTACH_ACTION))
{
att.resp_msg = "Action is not supported for virtual router VMs";
failure_response(ACTION, att);

View File

@ -33,6 +33,10 @@ enabled_tabs:
autorefresh: true
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: true
tabs:
dashboard-tab:
panel_tabs:

View File

@ -33,6 +33,10 @@ enabled_tabs:
autorefresh: true
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: false
tabs:
dashboard-tab:
panel_tabs:

View File

@ -5,6 +5,10 @@ enabled_tabs:
- settings-tab
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: true
tabs:
provision-tab:
panel_tabs:
@ -85,10 +89,18 @@ tabs:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
#- 3 # Group
- 4 # Name
- 5 # Reservation
- 6 # Cluster
#- 5 # Reservation
#- 6 # Cluster
#- 7 # Bridge
- 8 # Leases
#- 8 # Leases
#- 9 # VLAN ID
secgroups-tab:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
#- 5 # Labels

View File

@ -5,6 +5,10 @@ enabled_tabs:
- settings-tab
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: false
tabs:
provision-tab:
panel_tabs:
@ -92,3 +96,11 @@ tabs:
#- 7 # Bridge
- 8 # Leases
#- 9 # VLAN ID
secgroups-tab:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
#- 5 # Labels

View File

@ -33,6 +33,10 @@ enabled_tabs:
autorefresh: true
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: true
tabs:
dashboard-tab:
panel_tabs:

View File

@ -33,6 +33,10 @@ enabled_tabs:
autorefresh: true
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: false
tabs:
dashboard-tab:
panel_tabs:

View File

@ -33,6 +33,10 @@ enabled_tabs:
autorefresh: true
features:
showback: true
# Allows to change the security groups for each network interface
# on the VM creation dialog
secgroups: true
tabs:
dashboard-tab:
panel_tabs:

View File

@ -70,9 +70,6 @@ define(function(require) {
Sunstone.showTab(DASHBOARD_TAB_ID);
$('#loading').hide();
}
// init the zone list, needed for market & apps zone columns
Sunstone.runAction("Zone.list");
});
function _setupCloseDropdownsOnClick() {

View File

@ -17,6 +17,8 @@
define(function(require) {
var OpenNebulaAction = require('./action');
var Locale = require('utils/locale');
var Config = require('sunstone-config');
var OpenNebulaHelper = require('./helper');
var RESOURCE = "DATASTORE";
var STATES_STR = [
@ -40,6 +42,8 @@ define(function(require) {
FILE_DS : 2
};
var dsMadIndex = {};
var Datastore = {
"resource": RESOURCE,
"stateStr": function(stateId) {
@ -57,7 +61,17 @@ define(function(require) {
OpenNebulaAction.del(params, RESOURCE);
},
"list" : function(params) {
OpenNebulaAction.list(params, RESOURCE);
OpenNebulaAction.list(params, RESOURCE, null, function(response) {
var list = OpenNebulaHelper.pool(RESOURCE, response);
dsMadIndex = {};
$.each(list, function(){
dsMadIndex[ this[RESOURCE].ID ] = this[RESOURCE].DS_MAD;
});
return list;
});
},
"list_in_zone" : function(params) {
OpenNebulaAction.list_in_zone(params, RESOURCE);
@ -95,6 +109,33 @@ define(function(require) {
},
"getName": function(id){
return OpenNebulaAction.getName(id, RESOURCE);
},
"isMarketExportSupported": function(id){
var name = dsMadIndex[id];
if(name == undefined){
// When in doubt, allow the action and let oned return failure
return true;
}
var support = false;
$.each(Config.onedConf.DS_MAD_CONF, function(){
if (this.NAME == name){
support = (this.MARKETPLACE_ACTIONS != undefined &&
this.MARKETPLACE_ACTIONS.split(',').includes("export"));
return false; //break
}
});
return support;
},
"initMarketExportSupported": function(){
this.list({
timeout: true,
success: function (request, obj_list) {},
//error: Notifier.onError
});
}
}

View File

@ -80,7 +80,7 @@ define(function(require) {
},
"isNetworkChangeEnabled": function(template) {
if (template.VMTEMPLATE.TEMPLATE.SUNSTONE &&
template.VMTEMPLATE.TEMPLATE.SUNSTONE.NETWORK_SELECT !== 'NO') {
template.VMTEMPLATE.TEMPLATE.SUNSTONE.NETWORK_SELECT == 'NO') {
return false;
} else {
return true;

View File

@ -58,6 +58,11 @@ define(function(require) {
_addPanelsHooks(_tabId, panelsHooks);
}
var initHooks = tabObj.initHooks;
if (initHooks) {
_addInitHooks(_tabId, initHooks);
}
var dialogs = tabObj.dialogs;
if (dialogs) {
_addDialogs(dialogs)
@ -89,6 +94,11 @@ define(function(require) {
return false;
}
var _addInitHooks = function(tabId, hooks) {
SunstoneCfg["tabs"][tabId]['initHooks'] = hooks;
return false;
}
var _addPanels = function(tabId, panels) {
var indexedPanels = {}
$.each(panels, function(index, panel) {
@ -115,6 +125,14 @@ define(function(require) {
_insertButtonsInTab(tabName);
_setupDataTable(tabName);
var hooks = SunstoneCfg['tabs'][tabName].initHooks;
if (hooks) {
$.each(hooks, function(i, hook){
hook.init();
});
}
// TODO Add openenbula actions
/*if (config['view']['autorefresh']) {
var tabContext = $("#" + tabName);

View File

@ -19,6 +19,7 @@ define(function(require) {
var Notifier = require('utils/notifier');
var Locale = require('utils/locale');
var OpenNebulaResource = require('opennebula/image');
var OpenNebula = require('opennebula');
var OpenNebulaAction = require('opennebula/action');
var CommonActions = require('utils/common-actions');
@ -30,7 +31,7 @@ define(function(require) {
var CLONE_DIALOG_ID = require('./dialogs/clone/dialogId');
var CREATE_APP_DIALOG_ID = require('tabs/marketplaceapps-tab/form-panels/create/formPanelId');
var IMPORT_DIALOG_ID = require('./form-panels/import/formPanelId');
var CONFIRM_DIALOG_ID = require('utils/dialogs/generic-confirm/dialogId');
var _commonActions = new CommonActions(OpenNebulaResource, RESOURCE, TAB_ID, XML_ROOT);
@ -63,19 +64,52 @@ define(function(require) {
"Image.snapshot_delete": _commonActions.singleAction("snapshot_delete"),
"Image.export_dialog" : {
type: "custom",
call: function() {
Sunstone.showTab(MARKETPLACEAPPS_TAB_ID);
Sunstone.showFormPanel(MARKETPLACEAPPS_TAB_ID, CREATE_APP_DIALOG_ID, "export",
function(formPanelInstance, context) {
var selectedNodes = Sunstone.getDataTable(TAB_ID).elements();
if (selectedNodes.length !== 1) {
Notifier.notifyMessage(Locale.tr("Please select one (and just one) Image to export."));
return false;
}
call: function(params) {
var selectedNodes = Sunstone.getDataTable(TAB_ID).elements();
var resourceId = '' + selectedNodes[0];
formPanelInstance.setImageId(resourceId);
});
if (selectedNodes.length !== 1) {
Notifier.notifyMessage(Locale.tr("Please select one (and just one) Image to export."));
return false;
}
var resourceId = '' + selectedNodes[0];
OpenNebulaResource.show({
data : {
id: resourceId
},
success: function(request, img_json){
var img = img_json[XML_ROOT];
if (OpenNebula.Datastore.isMarketExportSupported(img.DATASTORE_ID)){
Sunstone.showTab(MARKETPLACEAPPS_TAB_ID);
Sunstone.showFormPanel(MARKETPLACEAPPS_TAB_ID, CREATE_APP_DIALOG_ID, "export",
function(formPanelInstance, context) {
formPanelInstance.setImageId(resourceId);
});
} else {
Sunstone.getDialog(CONFIRM_DIALOG_ID).setParams({
header : Locale.tr("Error"),
body : Locale.tr("This Image resides in Datastore ") +
img.DATASTORE_ID + " (" + img.DATASTORE + ")" +
Locale.tr(". The export action is not supported for that Datastore DS_MAD driver."),
question : "",
buttons : [
Locale.tr("Ok"),
],
submit : [
function(){
return false;
}
]
});
Sunstone.getDialog(CONFIRM_DIALOG_ID).reset();
Sunstone.getDialog(CONFIRM_DIALOG_ID).show();
}
},
error: Notifier.onError
});
}
},

View File

@ -35,6 +35,10 @@ define(function(require) {
require('../utils/hooks/header')
];
var _initHooks = [
require('./marketplaceapps-tab/hooks/init')
];
var _formPanels = [
require('./marketplaceapps-tab/form-panels/create'),
require('./marketplaceapps-tab/form-panels/export')
@ -55,6 +59,7 @@ define(function(require) {
dataTable: new Table(DATATABLE_ID, {actions: true, info: true, oneSelection: true}),
panels: _panels,
panelsHooks: _panelsHooks,
initHooks: _initHooks,
formPanels: _formPanels,
dialogs: _dialogs
};

View File

@ -28,6 +28,7 @@ define(function(require) {
var MarketPlacesTable = require('tabs/marketplaces-tab/datatable');
var Config = require('sunstone-config');
var WizardFields = require('utils/wizard-fields');
var OpenNebula = require('opennebula');
/*
TEMPLATES
@ -65,7 +66,13 @@ define(function(require) {
this.imagesTable = new ImagesTable(
FORM_PANEL_ID + 'imagesTable',
{'select': true});
{ 'select': true,
'selectOptions': {
'filter_fn': function(image) {
return OpenNebula.Datastore.isMarketExportSupported(image.DATASTORE_ID);
}
}
});
this.marketPlacesTable = new MarketPlacesTable(
FORM_PANEL_ID + 'marketPlacesTable',

View File

@ -0,0 +1,41 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, 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. */
/* -------------------------------------------------------------------------- */
define(function(require) {
var Sunstone = require('sunstone');
var OpenNebula = require('opennebula');
var Config = require('sunstone-config');
var ZONE_TAB_ID = require('tabs/zones-tab/tabId');
/*
FUNCTION DEFINITIONS
*/
function _init() {
// init the zone list, needed for market & apps zone columns
if (Config.isTabActionEnabled(ZONE_TAB_ID, "Zone.list")) {
Sunstone.runAction("Zone.list");
}
OpenNebula.Datastore.initMarketExportSupported();
}
return {
'init': _init
};
});

View File

@ -35,6 +35,10 @@ define(function(require) {
require('../utils/hooks/header')
];
var _initHooks = [
require('./marketplaceapps-tab/hooks/init')
];
var _formPanels = [
require('./marketplaces-tab/form-panels/create')
];
@ -54,6 +58,7 @@ define(function(require) {
dataTable: new Table(DATATABLE_ID, {actions: true, info: true, oneSelection: true}),
panels: _panels,
panelsHooks: _panelsHooks,
initHooks: _initHooks,
formPanels: _formPanels,
dialogs: _dialogs
};

View File

@ -0,0 +1,39 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, 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. */
/* -------------------------------------------------------------------------- */
define(function(require) {
var Sunstone = require('sunstone');
var OpenNebula = require('opennebula');
var Config = require('sunstone-config');
var ZONE_TAB_ID = require('tabs/zones-tab/tabId');
/*
FUNCTION DEFINITIONS
*/
function _init() {
// init the zone list, needed for market & apps zone columns
if (Config.isTabActionEnabled(ZONE_TAB_ID, "Zone.list")) {
Sunstone.runAction("Zone.list");
}
}
return {
'init': _init
};
});

View File

@ -917,7 +917,8 @@ define(function(require) {
}
if (Config.provision.create_vm.isEnabled("network_select")) {
NicsSection.insert(template_json, create_vm_context);
NicsSection.insert(template_json, create_vm_context,
{'securityGroups': Config.isFeatureEnabled("secgroups")});
} else {
$(".provision_network_selector", create_vm_context).html("");
}
@ -1108,42 +1109,9 @@ define(function(require) {
var context = $("#provision_create_flow");
if (body.custom_attrs) {
var network_attrs = [];
var text_attrs = [];
$.each(body.custom_attrs, function(key, value){
var parts = value.split("|");
// 0 mandatory; 1 type; 2 desc;
var attrs = {
"name": key,
"mandatory": parts[0],
"type": parts[1],
"description": parts[2],
}
switch (parts[1]) {
case "vnet_id":
network_attrs.push(attrs)
break;
case "text":
case "text64":
case "password":
text_attrs.push(attrs)
break;
}
})
if (network_attrs.length > 0) {
NicsSection.generate_provision_network_accordion(
$(".provision_network_selector", context), {hide_add_button:true});
$.each(network_attrs, function(index, vnet_attr){
NicsSection.generate_provision_network_table(
$(".provision_nic_accordion", context),
{vnet_attr: vnet_attr});
});
}
UserInputs.serviceTemplateInsert(
$(".provision_network_selector", context),
data);
} else {
$(".provision_network_selector", context).html("")
$(".provision_custom_attributes_selector", context).html("")
@ -1225,24 +1193,7 @@ define(function(require) {
return false;
}
var custom_attrs = {}
var missing_network = false;
if ($(".provision_nic_accordion", context)) {
$(".selected_network", $(".provision_nic_accordion", context)).each(function(){
if (!$(this).attr("opennebula_id")) {
$(this).css("color", "red");
missing_network = true;
} else {
$(this).css("color", "#777");
custom_attrs[$(this).attr("attr_name")] = $(this).attr("opennebula_id");
}
})
}
if (missing_network) {
$(".alert-box-error", context).fadeIn().html(Locale.tr("You have not specified all the Networks for this Service"));
return false;
}
var custom_attrs = WizardFields.retrieve($(".provision_network_selector", context));
var roles = [];

View File

@ -95,7 +95,7 @@
<div class="large-6 columns">
<div class="provision_disk_selector"></div>
</div>
<div class="large-6 columns">
<div class="small-12 columns">
<div class="provision_network_selector"></div>
</div>
<div class="large-6 columns">

View File

@ -181,7 +181,10 @@ define(function(require) {
}) );
DisksResize.insert(template_json, $(".disksContext" + template_json.VMTEMPLATE.ID, context));
NicsSection.insert(template_json, $(".nicsContext" + template_json.VMTEMPLATE.ID, context));
NicsSection.insert(template_json,
$(".nicsContext" + template_json.VMTEMPLATE.ID, context),
{'securityGroups': Config.isFeatureEnabled("secgroups")});
var inputs_div = $(".template_user_inputs" + template_json.VMTEMPLATE.ID, context);

View File

@ -34,7 +34,7 @@
</div>
<div class="large-6 small-12 columns disksContext{{element.ID}}"></div>
<div class="large-6 small-12 columns template_user_inputs{{element.ID}}"></div>
<div class="large-6 small-12 columns nicsContext{{element.ID}}">
<div class="small-12 columns nicsContext{{element.ID}}">
<div class="provision_network_selector">
</div>
</div>

View File

@ -54,16 +54,14 @@
</div>
<div class="row">
<div class="medium-6 columns">
<div class="row text-center">
<div class="row">
<div class="large-12 columns">
<h3 class="subheader">
<small>{{tr "REAL CPU"}}</small>
</h3>
<span>{{tr "REAL CPU"}}</span>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<div class="large-12 columns centered graph vm_cpu_graph text-center" style="height: 100px;">
<div class="large-12 columns centered graph vm_cpu_graph" style="height: 100px;">
<span id="provision_dashboard_total" style="font-size:80px">
<i class="fa fa-spinner fa-spin"></i>
</span>
@ -72,13 +70,13 @@
</div>
</div>
<div class="medium-6 columns">
<div class="row text-center">
<h3 class="subheader">
<small>{{tr "REAL MEMORY"}}</small>
</h3>
<div class="row">
<div class="large-12 columns">
<span>{{tr "REAL MEMORY"}}</span>
</div>
</div>
<div class="row">
<div class="large-12 columns centered graph vm_memory_graph text-center" style="height: 100px;">
<div class="large-12 columns centered graph vm_memory_graph" style="height: 100px;">
<span id="provision_dashboard_total" style="font-size:80px">
<i class="fa fa-spinner fa-spin"></i>
</span>

View File

@ -137,11 +137,11 @@ define(function(require) {
html += '\
<div class="row">\
<div class="medium-6 columns">\
<div class="row text-center">\
<h3 class="subheader"><small>' + Locale.tr("NET RX") + '</small></h3>\
<div class="row">\
<span>' + Locale.tr("NET RX") + '</span3>\
</div>\
<div class="row">\
<div class="large-12 columns centered graph text-center" id="vm_net_rx_graph" style="height: 100px;">\
<div class="large-12 columns centered graph" id="vm_net_rx_graph" style="height: 100px;">\
<span id="provision_dashboard_total" style="font-size:80px">\
<i class="fa fa-spinner fa-spin"></i>\
</span>\
@ -153,11 +153,11 @@ define(function(require) {
</div>\
</div>\
<div class="medium-6 columns">\
<div class="row text-center">\
<h3 class="subheader"><small>' + Locale.tr("NET TX") + '</small></h3>\
<div class="row">\
<span>' + Locale.tr("NET TX") + '</span3>\
</div>\
<div class="row">\
<div class="large-12 columns centered graph text-center" id="vm_net_tx_graph" style="height: 100px;">\
<div class="large-12 columns centered graph" id="vm_net_tx_graph" style="height: 100px;">\
<span id="provision_dashboard_total" style="font-size:80px">\
<i class="fa fa-spinner fa-spin"></i>\
</span>\
@ -169,11 +169,11 @@ define(function(require) {
</div>\
</div>\
<div class="medium-6 columns">\
<div class="row text-center">\
<h3 class="subheader"><small>' + Locale.tr("NET DOWNLOAD SPEED") + '</small></h3>\
<div class="row">\
<span>' + Locale.tr("NET DOWNLOAD SPEED") + '</span3>\
</div>\
<div class="row">\
<div class="large-12 columns centered graph text-center" id="vm_net_rx_speed_graph" style="height: 100px;">\
<div class="large-12 columns centered graph" id="vm_net_rx_speed_graph" style="height: 100px;">\
<span id="provision_dashboard_total" style="font-size:80px">\
<i class="fa fa-spinner fa-spin"></i>\
</span>\
@ -185,11 +185,11 @@ define(function(require) {
</div>\
</div>\
<div class="medium-6 columns">\
<div class="row text-center">\
<h3 class="subheader"><small>' + Locale.tr("NET UPLOAD SPEED") + '</small></h3>\
<div class="row">\
<span>' + Locale.tr("NET UPLOAD SPEED") + '</span3>\
</div>\
<div class="row">\
<div class="large-12 columns centered graph text-center" id="vm_net_tx_speed_graph" style="height: 100px;">\
<div class="large-12 columns centered graph" id="vm_net_tx_speed_graph" style="height: 100px;">\
<span id="provision_dashboard_total" style="font-size:80px">\
<i class="fa fa-spinner fa-spin"></i>\
</span>\

View File

@ -15,7 +15,7 @@
{{! -------------------------------------------------------------------------- }}
<form id="ar_list_form">
<div class="row collapse">
<div class="row">
<div class="large-12 columns">
{{#isTabActionEnabled "vnets-tab" "Network.add_ar"}}
<button class="button success small radius" id="add_ar_button">
@ -36,7 +36,7 @@
</span>
</div>
</div>
<div class="row collapse">
<div class="row">
<div class="large-12 columns" style="overflow:auto">
<table id="ar_list_datatable" class="datatable twelve">
<thead>

View File

@ -16,7 +16,7 @@
<form id="leases_form">
{{#isTabActionEnabled "vnets-tab" "Network.hold_lease"}}
<div class="row collapse">
<div class="row">
<div class="large-4 columns">
<input type="text" id="panel_hold_lease"/>
</div>
@ -27,7 +27,7 @@
</div>
</div>
{{/isTabActionEnabled}}
<div class="row collapse">
<div class="row">
<div class="large-12 columns" style="overflow:auto">
<table id="leases_datatable" class="datatable twelve">
<thead>

View File

@ -25,6 +25,7 @@ define(function(require) {
var Notifier = require('utils/notifier');
var NicsSection = require('utils/nics-section');
var WizardFields = require('utils/wizard-fields');
var Config = require('sunstone-config');
/*
CONSTANTS
@ -68,7 +69,10 @@ define(function(require) {
NicsSection.insert({},
$(".nicsContext", context),
{floatingIP: true, forceIPv4:true, management: true,
{ floatingIP: true,
forceIPv4:true,
management: true,
securityGroups: Config.isFeatureEnabled("secgroups"),
hide_add_button:true,
click_add_button:true
});

View File

@ -33,6 +33,7 @@ define(function(require) {
var OpenNebulaTemplate = require('opennebula/template');
var OpenNebulaAction = require('opennebula/action');
var Notifier = require('utils/notifier');
var Config = require('sunstone-config');
/*
TEMPLATES
@ -108,7 +109,10 @@ define(function(require) {
NicsSection.insert({},
$(".nicsContext", context),
{floatingIP: true, forceIPv4:true, management: true});
{ floatingIP: true,
forceIPv4:true,
management: true,
securityGroups: Config.isFeatureEnabled("secgroups")});
this.templatesTable.initialize();

View File

@ -20,15 +20,16 @@ define(function(require) {
var Notifier = require('utils/notifier');
var OpenNebula = require('opennebula');
var OpenNebulaTemplate = require('opennebula/template');
var TemplateSection = require('hbs!./nics-section/html');
var TemplateDD = require('hbs!./nics-section/dd');
var SecurityGroupsTable = require('tabs/secgroups-tab/datatable');
var VNetsTable = require('tabs/vnets-tab/datatable');
var provision_nic_accordion_id = 0;
var provision_nic_accordion_dd_id = 0;
return {
'insert': _insert,
'retrieve': _retrieve,
'generate_provision_network_accordion': _generate_provision_network_accordion,
'generate_provision_network_table': _generate_provision_network_table
'retrieve': _retrieve
}
/**
@ -44,6 +45,7 @@ define(function(require) {
* input to select the IPv4
* - management {bool}: true to show the
* management checkbox
* - securityGroups {bool}: true to select SGs
*/
function _insert(template_json, context, options) {
if (options == undefined){
@ -80,34 +82,61 @@ define(function(require) {
function _retrieve(context) {
var nics = [];
var nic;
$(".selected_network", context).each(function() {
if ($(this).attr("template_nic")) {
nic = JSON.parse($(this).attr("template_nic"))
} else if ($(this).attr("opennebula_id")) {
nic = {
'network_id': $(this).attr("opennebula_id")
}
$(".nic-section-entry", context).each(function() {
// template_nic is the original NIC definition in an instantiate action.
// We try to use it replacing only the settings offered in this
// module, to preserve any other potential settings (such as IP6_GLOBAL)
if ($(this).data("template_nic") != undefined) {
nic = $(this).data("template_nic");
} else {
nic = undefined;
nic = {};
}
if (nic) {
if ($("input.floating_ip", $(this)).prop("checked")){
nic["FLOATING_IP"] = "YES";
}
var val = $(this).data("vnetsTable").retrieveResourceTableSelect();
var ip4 = $("input.manual_ip4", $(this)).val();
if (ip4 != undefined && ip4 != ""){
nic["IP"] = ip4;
}
if ($("input.management", $(this)).prop("checked")){
nic["VROUTER_MANAGEMENT"] = "YES";
}
nics.push(nic);
if (val == undefined || val == ""){
if (nic["NETWORK"] == undefined && nic["NETWORK_ID"] == undefined )
// No network name or id in original NIC, and no selection done
return true; //continue
}
delete nic["NETWORK"];
delete nic["NETWORK_ID"];
delete nic["NETWORK_UNAME"];
nic["NETWORK_ID"] = val;
delete nic["FLOATING_IP"];
if ($("input.floating_ip", $(this)).prop("checked")){
nic["FLOATING_IP"] = "YES";
}
delete nic["IP"];
var ip4 = $("input.manual_ip4", $(this)).val();
if (ip4 != undefined && ip4 != ""){
nic["IP"] = ip4;
}
delete nic["VROUTER_MANAGEMENT"];
if ($("input.management", $(this)).prop("checked")){
nic["VROUTER_MANAGEMENT"] = "YES";
}
var sgTable = $(this).data("sgTable");
if (sgTable){
delete nic["SECURITY_GROUPS"];
var secgroups = sgTable.retrieveResourceTableSelect();
if (secgroups != undefined && secgroups.length != 0) {
nic["SECURITY_GROUPS"] = secgroups.join(",");
}
}
nics.push(nic);
});
return nics
@ -117,13 +146,13 @@ define(function(require) {
* @param {object} context JQuery selector
* @param {object} options Options
* - nic {object}
* - vnet_attr {object}
* - floatingIP {bool}: true to show the
* floating IP checkbox
* - forceIPv4 {bool}: true to show the
* input to select the IPv4
* - management {bool}: true to show the
* management checkbox
* - securityGroups {bool}: true to select SGs
*/
function _generate_provision_network_table(context, options) {
context.off();
@ -133,212 +162,86 @@ define(function(require) {
options = {};
}
if (options.nic) {
nic_span = '<span class="selected_network" template_nic=\'' + JSON.stringify(options.nic) + '\'>' +
'<span>' + Locale.tr("INTERFACE") + " </span>" +
'<span>' + (options.nic.NETWORK || options.nic.NETWORK_ID) + "</span>" +
'</span>' +
'<span class="button right hollow tiny alert provision_remove_nic">' +
'<i class="fa fa-times"/>' +
'</span>' +
'<span class="button right hollow tiny">' +
'<i class="fa fa-pencil"/>' +
'</span>';
} else if (options.vnet_attr) {
nic_span = '<span>' + options.vnet_attr.description + "</span><br>" +
'<span class="selected_network only-not-active" attr_name=\'' + options.vnet_attr.name + '\'>' +
'<span>' + Locale.tr("INTERFACE") + " </span>" +
'<span class="label secondary">' + Locale.tr("Select a Network") + "</span>" +
'</span>' +
'<span class="only-active">' +
Locale.tr("Select a Network for this interface") +
'</span>' +
'<span class="button right hollow tiny only-not-active">' +
'<i class="fa fa-pencil"/>' +
'</span>';
} else {
nic_span =
'<span class="selected_network only-not-active">' +
'<span>' + Locale.tr("INTERFACE") + " </span>" +
'<span class="label secondary">' + Locale.tr("Select a Network") + "</span>" +
'</span>' +
'<span class="only-active">' +
Locale.tr("Select a Network for this interface") +
'</span>' +
'<span class="button right hollow tiny alert provision_remove_nic">' +
'<i class="fa fa-times"/>' +
'</span>' +
'<span class="button right hollow tiny only-not-active">' +
'<i class="fa fa-pencil"/>' +
'</span>';
var vnetsTable = new VNetsTable(
'vnet_nics_section_'+provision_nic_accordion_dd_id,
{ 'select': true });
var sgTable;
var sgHtml = "";
if (options.securityGroups == true){
sgTable = new SecurityGroupsTable(
'sg_nics_section_'+provision_nic_accordion_dd_id,
{ 'select': true,
'selectOptions': { 'multiple_choice': true }
});
sgHtml = sgTable.dataTableHTML;
}
var dd_context = $('<dd class="accordion-item" data-accordion-item>' +
'<a href="#provision_accordion_dd_' + provision_nic_accordion_dd_id + '" class="accordion-title">' +
nic_span +
'</a>' +
'<div id="provision_accordion_dd_' + provision_nic_accordion_dd_id + '" class="accordion-content" data-tab-content>' +
'<div class="row">' +
'<div class="large-12 large-centered columns">' +
'<h3 class="subheader">' +
'<input type="search" class="provision-search-input" placeholder="Search"/>' +
'</h3>' +
'<br>' +
'</div>' +
'</div>' +
'<div class="row">' +
'<div class="large-12 large-centered columns">' +
'<table class="provision_networks_table">' +
'<thead hidden>' +
'<tr>' +
'<th>' + Locale.tr("ID") + '</th>' +
'<th>' + Locale.tr("Name") + '</th>' +
'</tr>' +
'</thead>' +
'<tbody hidden>' +
'</tbody>' +
'</table>' +
'<br>' +
'</div>' +
'</div>' +
'</div>' +
'</dd>').appendTo(context);
var dd_context = $(TemplateDD({
vnetsTableHTML: vnetsTable.dataTableHTML,
securityGroupsTableHTML: sgHtml,
provision_nic_accordion_dd_id: provision_nic_accordion_dd_id,
options: options
})).appendTo(context);
$(".nic-section-entry", dd_context).data("template_nic", options.nic);
$(".nic-section-entry", dd_context).data("vnetsTable", vnetsTable);
$(".nic-section-entry", dd_context).data("sgTable", sgTable);
Tips.setup(dd_context);
Foundation.reInit(context);
provision_nic_accordion_dd_id += 1;
var provision_networks_datatable = $('.provision_networks_table', dd_context).dataTable({
"iDisplayLength": 6,
"sDom" : '<"H">t<"F"lp>',
"aLengthMenu": [[6, 12, 36, 72], [6, 12, 36, 72]],
"aoColumnDefs": [
{"bVisible": false, "aTargets": ["all"]}
],
"aoColumns": [
{"mDataProp": "VNET.ID"},
{"mDataProp": "VNET.NAME"}
],
"fnPreDrawCallback": function (oSettings) {
// create a thumbs container if it doesn't exist. put it in the dataTables_scrollbody div
if (this.$('tr', {"filter": "applied"}).length == 0) {
this.html('<div class="text-center">' +
'<span class="fa-stack fa-5x">' +
'<i class="fa fa-cloud fa-stack-2x"></i>' +
'<i class="fa fa-info-circle fa-stack-1x fa-inverse"></i>' +
'</span>' +
'<br>' +
'<br>' +
'<span>' +
Locale.tr("There are no networks available. Please contact your cloud administrator") +
'</span>' +
'</div>');
} else {
$(".provision_networks_table", dd_context).html(
'<div class="provision_networks_ul large-up-3 medium-up-3 small-up-1 text-center">' +
'</div>');
}
vnetsTable.initialize();
vnetsTable.refreshResourceTableSelect();
return true;
},
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
var data = aData.VNET;
$(".provision_networks_ul", dd_context).append(
'<div class="column">' +
'<ul class="provision-pricing-table hoverable more-than-one menu vertical" opennebula_id="' + data.ID + '" opennebula_name="' + data.NAME + '">' +
'<li class="provision-title" title="' + data.NAME + '">' +
data.NAME +
'</li>' +
'<li class="provision-bullet-item">' +
'<i class="fa fa-fw fa-globe"/>' +
'</li>' +
'<li class="provision-description">' +
(data.TEMPLATE.DESCRIPTION || '...') +
'</li>' +
'</ul>' +
'</div>');
if (options.securityGroups == true){
sgTable.initialize();
sgTable.refreshResourceTableSelect();
}
return nRow;
if (options.nic != undefined){
var selectedResources;
if (options.nic.NETWORK_ID != undefined) {
selectedResources = {
ids : templateJSON.NETWORK_ID
}
} else if (options.nic.NETWORK != undefined && options.nic.NETWORK_UNAME != undefined) {
selectedResources = {
names : {
name: options.nic.NETWORK,
uname: options.nic.NETWORK_UNAME
}
}
}
if (selectedResources != undefined){
vnetsTable.selectResourceTableSelect(selectedResources);
vnetsTable.idInput().data("prev", vnetsTable.idInput().val());
}
if (options.securityGroups == true && options.nic.SECURITY_GROUPS != undefined){
sgTable.selectResourceTableSelect({ids: options.nic.SECURITY_GROUPS.split(',')});
}
}
vnetsTable.idInput().on("change", function(){
$(".selected_network", dd_context).text(OpenNebula.Network.getName($(this).val()));
});
$('.provision-search-input', dd_context).on('input', function() {
provision_networks_datatable.fnFilter($(this).val());
})
dd_context.on("click", ".provision-pricing-table.more-than-one" , function() {
var html =
'<span>' + Locale.tr("INTERFACE") + " </span>" +
'<span>' + $(this).attr("opennebula_name") + "</span>";
if (options.floatingIP){
html +=
'<div class="row noclick">' +
'<div class="small-12 columns">' +
'<label class="inline">' +
'<input type="checkbox" class="floating_ip" />' +
Locale.tr("Floating IP") + " " +
'<span class="tip">' +
Locale.tr("If checked, each Virtual Machine will have a floating IP added to its network interface.") +
'</span>' +
'</label>' +
'</div>' +
'</div>';
}
if (options.forceIPv4){
html +=
'<div class="row noclick">' +
'<div class="small-5 columns">' +
'<label class="right inline">' +
Locale.tr("Force IPv4:") + " " +
'<span class="tip">' +
Locale.tr("Optionally, you can force the IP assigned to the network interface.") +
'</span>' +
'</label>' +
'</div>' +
'<div class="small-7 columns">' +
'<input type="text" class="manual_ip4" />' +
'</div>' +
'</div>';
}
if (options.management){
html +=
'<div class="noclick">' +
'<label>' +
'<input type="checkbox" class="management" />' +
Locale.tr("Management Interface") + " " +
'<span class="tip">' +
Locale.tr("If checked, this network interface will be a Virtual Router management interface. Traffic will not be forwarded.") +
'</span>' +
'</label>' +
'</div>';
}
$(".selected_network", dd_context).html(html);
$(".selected_network", dd_context).attr("opennebula_id", $(this).attr("opennebula_id"))
$(".selected_network", dd_context).removeAttr("template_nic")
Tips.setup($(".selected_network", dd_context));
$('a', dd_context).first().trigger("click");
})
dd_context.on("click", ".provision_remove_nic" , function() {
dd_context.remove();
return false;
});
dd_context.on("click", ".noclick" , function(event) {
event.stopPropagation();
});
if (!options.nic && !options.vnet_attr) {
if (!options.nic) {
$('a', dd_context).trigger("click");
}
update_provision_networks_datatable(provision_networks_datatable);
}
/**
@ -352,28 +255,18 @@ define(function(require) {
* input to select the IPv4
* - management {bool}: true to show the
* management checkbox
* - securityGroups {bool}: true to select SGs
*/
function _generate_provision_network_accordion(context, options) {
context.off();
context.html(
'<fieldset>' +
'<legend>' +
'<i class="fa fa-globe"></i> ' +
Locale.tr("Network") +
'</legend>' +
'<div>' +
'<dl class="accordion provision_nic_accordion" data-accordion data-allow-all-closed="true">' +
'</dl>' +
'<a class="button small provision_add_network_interface"' + (options.hide_add_button ? 'hidden' : '') + '>' +
Locale.tr("Add another Network Interface") +
'</a>' +
'</div>' +
'</fieldset>')
context.html(TemplateSection());
if (options.hide_add_button == true){
$(".provision_add_network_interface", context).hide();
}
Foundation.reflow(context, 'accordion');
provision_nic_accordion_id += 1;
$(".provision_add_network_interface", context).on("click", function() {
_generate_provision_network_table($(".accordion", context), options);
});
@ -381,8 +274,6 @@ define(function(require) {
if (options.click_add_button == true){
$(".provision_add_network_interface", context).click();
}
//TODO $(document).foundation();
}
function update_provision_networks_datatable(datatable) {

View File

@ -0,0 +1,76 @@
<dd class="accordion-item" data-accordion-item>
<a href="#provision_accordion_dd_{{provision_nic_accordion_dd_id}}" class="accordion-title">
<i class="only-not-active fa fa-angle-double-down"/>&nbsp;
<i class="only-active fa fa-angle-double-up"/>&nbsp;
{{tr "Interface"}}&nbsp;
<span class="selected_network">
{{#if options.nic}}
{{#if options.nic.NETWORK}}
{{options.nic.NETWORK}}
{{else}}
{{options.nic.NETWORK_ID}}
{{/if}}
{{else}}
<span class="label secondary">{{tr "Select a Network"}} </span>
{{/if}}
</span>
<i class="right fa fa-times-circle remove-tab provision_remove_nic"></i>
</a>
<div id="provision_accordion_dd_{{provision_nic_accordion_dd_id}}" class="accordion-content nic-section-entry" data-tab-content>
<div class="row collapse">
{{{vnetsTableHTML}}}
</div>
{{#if options.forceIPv4}}
<div class="row">
<div class="small-5 columns">
<label class="right inline">
{{tr "Force IPv4:"}}
<span class="tip">
{{tr "Optionally, you can force the IP assigned to the network interface."}}
</span>
</label>
</div>
<div class="small-7 columns">
<input type="text" class="manual_ip4" />
</div>
</div>
{{/if}}
{{#if options.floatingIP}}
<div class="row">
<div class="small-12 columns">
<label class="inline">
<input type="checkbox" class="floating_ip" />
{{tr "Floating IP"}}
<span class="tip">
{{tr "If checked, each Virtual Machine will have a floating IP added to its network interface."}}
</span>
</label>
</div>
</div>
{{/if}}
{{#if options.management}}
<div class="row">
<div class="small-12 columns">
<label>
<input type="checkbox" class="management" />
{{tr "Management Interface"}}
<span class="tip">
{{tr "If checked, this network interface will be a Virtual Router management interface. Traffic will not be forwarded."}}
</span>
</label>
</div>
</div>
{{/if}}
{{#if options.securityGroups}}
<div class="row collapse">
<h6>
{{tr "Security Groups"}}&nbsp;
<span class="tip">
{{tr "You can add Security Groups to this network interface. These IDs do not overwrite the ones defined in the Virtual Network. All the Security Group IDs are combined, and applied to the Virtual Machine instance."}}
</span>
</h6>
{{{securityGroupsTableHTML}}}
</div>
{{/if}}
</div>
</dd>

View File

@ -0,0 +1,12 @@
<fieldset>
<legend>
<i class="fa fa-globe"></i> {{tr "Network"}}
</legend>
<div>
<dl class="accordion provision_nic_accordion" data-accordion data-allow-all-closed="true">
</dl>
<a class="button small provision_add_network_interface">
{{tr "Add another Network Interface"}}
</a>
</div>
</fieldset>

View File

@ -43,7 +43,7 @@ define(function(require) {
fromJSONtoHTMLTable(templateJSON, resourceType) +
'<tr>\
<td class="key_td"><input type="text" name="new_key" id="new_key" /></td>\
<td class="value_td"><textarea rows="1" type="text" name="new_value" id="new_value"></textarea></td>\
<td class="value_td"><textarea type="text" name="new_value" id="new_value"></textarea></td>\
<td class="text-right"><button type="button" id="button_add_value" class="button small secondary">' + Locale.tr("Add") + '</button>\</td>\
</tr>' +
'</table>'

View File

@ -501,7 +501,7 @@ define(function(require) {
});
}
if (that.labelsColumn) {
if (that.labelsColumn && !SunstoneConfig.isTabEnabled("provision-tab")) {
LabelsUtils.insertLabelsMenu({'tabName': that.tabId});
LabelsUtils.insertLabelsDropdown(that.tabId);
}

View File

@ -1,4 +1,4 @@
.right-content {
.tab:not(#provision-tab) {
margin-top: -2rem;
}
@ -19,7 +19,6 @@
.logo-header {
margin-top: 0.5rem;
}
}
.provision-logo {

View File

@ -1,8 +1,20 @@
table {
input {
input,
button,
select,
textarea {
margin-bottom: 0px !important;
}
textarea {
height: $input-font-size + ($form-spacing * 1.5) - rem-calc(1);
min-height: 0;
}
select {
padding: 0 0.5rem;
}
thead {
border: 0;

View File

@ -62,4 +62,10 @@
& > .tabs-panel {
padding: 0 !important;
}
}
.wizard_tabs {
a {
padding: 0.5rem 1.5rem;
}
}

View File

@ -1133,58 +1133,30 @@ int VirtualMachine::parse_pci(string& error_str)
int VirtualMachine::parse_graphics(string& error_str)
{
vector<Attribute *> array_graphics;
VectorAttribute * graphics;
VectorAttribute * user_graphics = user_obj_template->get("GRAPHICS");
vector<Attribute *>::iterator it;
int num = user_obj_template->remove("GRAPHICS", array_graphics);
for (it=array_graphics.begin(); it != array_graphics.end(); it++)
{
obj_template->set(*it);
}
if ( num == 0 )
if ( user_graphics == 0 )
{
return 0;
}
graphics = dynamic_cast<VectorAttribute * >(array_graphics[0]);
VectorAttribute * graphics = new VectorAttribute(user_graphics);
if ( graphics == 0 )
user_obj_template->erase("GRAPHICS");
obj_template->set(graphics);
if ( !graphics->vector_value("PORT").empty() )
{
return 0;
}
unsigned int port;
string port = graphics->vector_value("PORT");
int port_i;
int rc = graphics->vector_value("PORT", port);
int rc = graphics->vector_value("PORT", port_i);
if ( port.empty() )
{
Nebula& nd = Nebula::instance();
ostringstream oss;
istringstream iss;
int base_port;
string base_port_s;
int limit = 65535;
nd.get_configuration_attribute("VNC_BASE_PORT",base_port_s);
iss.str(base_port_s);
iss >> base_port;
oss << ( base_port + ( oid % (limit - base_port) ));
graphics->replace("PORT", oss.str());
}
else if ( rc == -1 || port_i < 0 )
{
error_str = "Wrong PORT number in GRAPHICS attribute";
return -1;
if (rc == -1 || port > 65535 )
{
error_str = "Wrong PORT number in GRAPHICS attribute";
return -1;
}
}
string random_passwd = graphics->vector_value("RANDOM_PASSWD");
@ -3588,36 +3560,6 @@ void VirtualMachine::disk_extended_info(int uid,
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool VirtualMachine::volatile_disk_extended_info(Template *tmpl)
{
int num;
vector<VectorAttribute * > disks;
DatastorePool * ds_pool = Nebula::instance().get_dspool();
bool found = false;
num = tmpl->get("DISK", disks);
for(int i=0; i<num; i++)
{
if ( !is_volatile(disks[i]) )
{
continue;
}
found = true;
if (hasHistory())
{
ds_pool->disk_attribute(get_ds_id(), disks[i]);
}
}
return found;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -25,13 +25,6 @@
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
time_t VirtualMachinePool::_monitor_expiration;
bool VirtualMachinePool::_submit_on_hold;
float VirtualMachinePool::_default_cpu_cost;
float VirtualMachinePool::_default_mem_cost;
float VirtualMachinePool::_default_disk_cost;
const char * VirtualMachinePool::import_table = "vm_import";
const char * VirtualMachinePool::import_db_names = "deploy_id, vmid";
@ -40,7 +33,6 @@ const char * VirtualMachinePool::import_db_bootstrap =
"CREATE TABLE IF NOT EXISTS vm_import "
"(deploy_id VARCHAR(128), vmid INTEGER, PRIMARY KEY(deploy_id))";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -55,7 +47,10 @@ VirtualMachinePool::VirtualMachinePool(
float default_cpu_cost,
float default_mem_cost,
float default_disk_cost)
: PoolSQL(db, VirtualMachine::table, true, false)
: PoolSQL(db, VirtualMachine::table, true, false),
_monitor_expiration(expire_time), _submit_on_hold(on_hold),
_default_cpu_cost(default_cpu_cost), _default_mem_cost(default_mem_cost),
_default_disk_cost(default_disk_cost)
{
string name;
@ -64,12 +59,6 @@ VirtualMachinePool::VirtualMachinePool(
string arg;
bool remote;
_monitor_expiration = expire_time;
_submit_on_hold = on_hold;
_default_cpu_cost = default_cpu_cost;
_default_mem_cost = default_mem_cost;
_default_disk_cost= default_disk_cost;
if ( _monitor_expiration == 0 )
{
clean_all_monitoring();

View File

@ -36,6 +36,7 @@ ENV['LANG'] = 'C'
$: << LIB_LOCATION+'/ruby/vendors/rbvmomi/lib'
$: << LIB_LOCATION+'/ruby'
require 'ostruct'
require 'rbvmomi'
require 'yaml'
require 'opennebula'
@ -135,6 +136,22 @@ class VIClient
return entities
end
# Only retrieve properties with faster search
def get_entities_to_import(folder, type)
res = folder.inventory_flat(type => :all)
objects = []
res.each {|k,v|
if k.to_s.split('(').first == type
obj = {}
v.propSet.each{ |dynprop|
obj[dynprop.name] = dynprop.val
}
objects << OpenStruct.new(obj)
end
}
return objects
end
############################################################################
# Initializr the VIClient, and creates an OpenNebula client. The parameters
@ -368,11 +385,13 @@ class VIClient
datacenters = get_entities(@root, 'Datacenter')
datacenters.each { |dc|
vms = get_entities(dc.vmFolder, 'VirtualMachine')
vms = get_entities_to_import(dc.vmFolder, 'VirtualMachine')
tmp = vms.select { |v| v.config && (v.config.template == true) }
one_tmp = []
one_tmp = []
host_cache = {}
ds_cache = {}
tmp.each { |t|
vi_tmp = VCenterVm.new(self, t)
@ -380,15 +399,28 @@ class VIClient
if !tpool["VMTEMPLATE/TEMPLATE/PUBLIC_CLOUD[\
TYPE=\"vcenter\" \
and VM_TEMPLATE=\"#{vi_tmp.vm.config.uuid}\"]"]
hostname = vi_tmp.vm.runtime.host.parent.name
# Check cached objects
if !host_cache[vi_tmp.vm.runtime.host.to_s]
host_cache[vi_tmp.vm.runtime.host.to_s] =
VCenterCachedHost.new vi_tmp.vm.runtime.host
end
if !ds_cache[t.datastore[0].to_s]
ds_cache[t.datastore[0].to_s] =
VCenterCachedDatastore.new t.datastore[0]
end
host = host_cache[vi_tmp.vm.runtime.host.to_s]
ds = ds_cache[t.datastore[0].to_s]
one_tmp << {
:name => "#{vi_tmp.vm.name} - #{hostname}",
:name => "#{vi_tmp.vm.name} - #{host.cluster_name}",
:uuid => vi_tmp.vm.config.uuid,
:host => hostname,
:one => vi_tmp.to_one,
:ds => vi_tmp.to_one_ds,
:default_ds => t.datastore[0].name,
:rp => vi_tmp.to_one_rp
:host => host.cluster_name,
:one => vi_tmp.to_one(host),
:ds => vi_tmp.to_one_ds(host, ds.name),
:default_ds => ds.name,
:rp => vi_tmp.to_one_rp(host)
}
end
}
@ -889,6 +921,95 @@ class VIClient
end
end
###########
# Cached Classes to speed up import and monitorization
############
class VCenterCachedHost
def initialize(rbVmomiHost)
@host = rbVmomiHost
@attributes = Hash.new
end
def name
if !@attributes['name']
@attributes['name']=@host.parent.name
end
@attributes['name']
end
def cluster_name
if !@attributes['cluster_name']
@attributes['cluster_name']=@host.parent.name
end
@attributes['cluster_name']
end
def ds_list
if !@attributes['ds_list']
@attributes['ds_list']=""
@host.parent.parent.parent.datastoreFolder.childEntity.each { |ds|
@attributes['ds_list'] += ds.name + ","
}
@attributes['ds_list']=@attributes['ds_list'][0..-2]
end
@attributes['ds_list']
end
def rp_list
if !@attributes['rp_list']
@attributes['rp_list']=""
@host.parent.resourcePool.resourcePool.each{|rp|
@attributes['rp_list'] += get_child_rp_names(rp, "")
}
@attributes['rp_list']=@attributes['rp_list'][0..-2]
end
@attributes['rp_list']
end
def get_child_rp_names(rp, parent_prefix)
rp_str = ""
current_rp = (parent_prefix.empty? ? "" : parent_prefix + "/")
current_rp += rp.name
if rp.resourcePool.size != 0
rp.resourcePool.each{|child_rp|
rp_str += get_child_rp_names(child_rp, current_rp)
}
end
rp_str += current_rp + ","
return rp_str
end
def cpumhz
if !@attributes['cpumhz']
@attributes['cpumhz']=@host.summary.hardware.cpuMhz.to_f
end
@attributes['cpumhz']
end
end
class VCenterCachedDatastore
def initialize(rbVmomiDatastore)
@ds = rbVmomiDatastore
@attributes = Hash.new
end
def name
if !@attributes['name']
@attributes['name']=@ds.name
end
@attributes['name']
end
end
################################################################################
# This class is an OpenNebula hosts that abstracts a vCenter cluster. It
# includes the functionality needed to monitor the cluster and report the ESX
@ -1115,8 +1236,18 @@ class VCenterHost < ::OpenNebula::Host
}
end
host_cache = {}
rp.vm.each { |v|
begin
# Check cached objects
if !host_cache[v.runtime.host.to_s]
host_cache[v.runtime.host.to_s] =
VCenterCachedHost.new v.runtime.host
end
host = host_cache[v.runtime.host.to_s]
name = v.name
number = -1
# Extract vmid if possible
@ -1128,16 +1259,16 @@ class VCenterHost < ::OpenNebula::Host
number = extraconfig_vmid[0][:value]
end
vm = VCenterVm.new(@client, v)
vm.monitor
vm.monitor(host)
next if !vm.vm.config
str_info << "\nVM = ["
str_info << "ID=#{number},"
str_info << "DEPLOY_ID=\"#{vm.vm.config.uuid}\","
str_info << "VM_NAME=\"#{name} - "\
"#{v.runtime.host.parent.name}\","
"#{host.cluster_name}\","
if number == -1
vm_template_to_one =
Base64.encode64(vm.vm_to_one).gsub("\n","")
Base64.encode64(vm.vm_to_one(host)).gsub("\n","")
str_info << "IMPORT_TEMPLATE=\"#{vm_template_to_one}\","
end
str_info << "POLL=\"#{vm.info}\"]"
@ -1353,7 +1484,6 @@ class VCenterVm
else
detach_attached_disks(vm, disks, hostname)
end
exit -1
vm.Destroy_Task.wait_for_completion
when "SHUTDOWN_POWEROFF", "SHUTDOWN_UNDEPLOY"
begin
@ -1533,7 +1663,7 @@ class VCenterVm
########################################################################
# Initialize the vm monitor information
########################################################################
def monitor
def monitor(host)
@summary = @vm.summary
@state = state_to_c(@summary.runtime.powerState)
@ -1548,9 +1678,7 @@ class VCenterVm
end
@used_memory = @summary.quickStats.hostMemoryUsage * 1024
host = @vm.runtime.host
cpuMhz = host.summary.hardware.cpuMhz.to_f
cpuMhz = host.cpumhz
@used_cpu =
((@summary.quickStats.overallCpuUsage.to_f / cpuMhz) * 100).to_s
@ -1560,7 +1688,7 @@ class VCenterVm
@used_memory = 0 if @used_memory.to_i < 0
@used_cpu = 0 if @used_cpu.to_i < 0
@esx_host = @vm.summary.runtime.host.name
@esx_host = host.name
@guest_ip = @vm.guest.ipAddress
@guest_state = @vm.guest.guestState
@vmware_tools = @vm.guest.toolsRunningStatus
@ -1607,8 +1735,8 @@ class VCenterVm
########################################################################
# Generates an OpenNebula Template for this VCenterVm
########################################################################
def to_one
cluster_name = @vm.runtime.host.parent.name
def to_one(host)
cluster_name = host.cluster_name
str = "NAME = \"#{@vm.name} - #{cluster_name}\"\n"\
"CPU = \"#{@vm.config.hardware.numCPU}\"\n"\
@ -1656,17 +1784,13 @@ class VCenterVm
########################################################################
# Generates a Datastore user input
########################################################################
def to_one_ds
def to_one_ds(host, default_ds)
# Datastores User Input
ds_str = ""
@vm.runtime.host.parent.parent.parent.datastoreFolder.childEntity.each { |ds|
ds_str += ds.name + ","
}
ds_str = ds_str[0..-2]
str = ""
if ds_str != ""
if host.ds_list != ""
str = "M|list|Which datastore you want this VM to run on?|"\
<< "#{ds_str}|#{ds_str.split(",")[0]}"
<< "#{host.ds_list}|#{default_ds}"
end
return str
@ -1675,34 +1799,16 @@ class VCenterVm
########################################################################
# Generates a Resource Pool user input
########################################################################
def to_one_rp
rp_str = ""
def to_one_rp(host)
# Resource Pool User Input
str = ""
@vm.runtime.host.parent.resourcePool.resourcePool.each{|rp|
rp_str += get_child_rp_names(rp, "")
}
rp_str = rp_str[0..-2]
return "M|list|Which resource pool you want this VM to run"\
" in?|#{rp_str}|#{rp_str.split(",")[0]}"
end
def get_child_rp_names(rp, parent_prefix)
rp_str = ""
current_rp = (parent_prefix.empty? ? "" : parent_prefix + "/")
current_rp += rp.name
if rp.resourcePool.size != 0
rp.resourcePool.each{|child_rp|
rp_str += get_child_rp_names(child_rp, current_rp)
}
if host.rp_list != ""
str = "M|list|Which resource pool you want this VM to run"\
" in?|#{host.rp_list}|#{host.rp_list.split(",")[0]}"
end
rp_str += current_rp + ","
return rp_str
return str
end
########################################################################
@ -1710,8 +1816,8 @@ class VCenterVm
#
#
########################################################################
def vm_to_one
host_name = @vm.runtime.host.parent.name
def vm_to_one(host)
cluster_name = host.cluster_name
state = case state_to_c(@summary.runtime.powerState)
when 'a'
@ -1720,7 +1826,7 @@ class VCenterVm
"POWEROFF"
end
str = "NAME = \"#{@vm.name} - #{host_name}\"\n"\
str = "NAME = \"#{@vm.name} - #{cluster_name}\"\n"\
"CPU = \"#{@vm.config.hardware.numCPU}\"\n"\
"vCPU = \"#{@vm.config.hardware.numCPU}\"\n"\
"MEMORY = \"#{@vm.config.hardware.memoryMB}\"\n"\
@ -1728,11 +1834,11 @@ class VCenterVm
"PUBLIC_CLOUD = [\n"\
" TYPE =\"vcenter\",\n"\
" VM_TEMPLATE =\"#{@vm.config.uuid}\",\n"\
" HOST =\"#{host_name}\"\n"\
" HOST =\"#{cluster_name}\"\n"\
"]\n"\
"IMPORT_VM_ID = \"#{@vm.config.uuid}\"\n"\
"IMPORT_STATE = \"#{state}\"\n"\
"SCHED_REQUIREMENTS=\"NAME=\\\"#{host_name}\\\"\"\n"
"SCHED_REQUIREMENTS=\"NAME=\\\"#{cluster_name}\\\"\"\n"
vp = @vm.config.extraConfig.select{|v|
v[:key].downcase=="remotedisplay.vnc.port"}
@ -1750,7 +1856,7 @@ class VCenterVm
if @vm.config.annotation.nil? || @vm.config.annotation.empty?
str << "DESCRIPTION = \"vCenter Virtual Machine imported by"\
" OpenNebula from Cluster #{@vm.runtime.host.parent.name}\"\n"
" OpenNebula from Cluster #{cluster_name}\"\n"
else
notes = @vm.config.annotation.gsub("\\", "\\\\").gsub("\"", "\\\"")
str << "DESCRIPTION = \"#{notes}\"\n"