DBNAME="vim_db"
QUIET_MODE=""
#TODO update it with the last database version
-LAST_DB_VERSION=22
+LAST_DB_VERSION=23
# Detect paths
MYSQL=$(which mysql)
#[ $OPENVIM_VER_NUM -ge 5017 ] && DATABASE_TARGET_VER_NUM=20 #0.5.17 => 20
#[ $OPENVIM_VER_NUM -ge 5018 ] && DATABASE_TARGET_VER_NUM=21 #0.5.18 => 21
#[ $OPENVIM_VER_NUM -ge 5021 ] && DATABASE_TARGET_VER_NUM=22 #0.5.21 => 22
+#[ $OPENVIM_VER_NUM -ge 5024 ] && DATABASE_TARGET_VER_NUM=23 #0.5.24 => 23
# TODO ... put next versions here
function upgrade_to_1(){
sql "DELETE FROM schema_version WHERE version_int = '22';"
}
+function upgrade_to_23(){
+ echo " Add 'hypervisor' and 'os_type' column to 'instances' table"
+ sql "ALTER TABLE instances ADD COLUMN hypervisor enum('kvm','xen-unik','xenhvm') NOT NULL DEFAULT 'kvm' AFTER flavor_id;"
+ sql "ALTER TABLE instances ADD COLUMN os_image_type VARCHAR(24) NOT NULL DEFAULT 'other' AFTER hypervisor;"
+ echo " Add 'hypervisors' column to 'hosts' table"
+ sql "ALTER TABLE hosts ADD COLUMN hypervisors VARCHAR(255) NOT NULL DEFAULT 'kvm' AFTER features;"
+ sql "INSERT INTO schema_version (version_int, version, openvim_ver, comments, date) "\
+ "VALUES (23, '0.23', '0.5.24', 'Add hypervisor, os_type to instances and add hypervisors to hosts', '2018-03-20');"
+}
+
+function downgrade_from_23(){
+ echo " Remove 'hypervisor' and 'os_type' column from 'instances' table"
+ sql "ALTER TABLE instances DROP COLUMN hypervisor;"
+ sql "ALTER TABLE instances DROP COLUMN os_image_type;"
+ echo " Remove 'hypervisors' column from 'hosts' table"
+ sql "ALTER TABLE hosts DROP COLUMN hypervisors;"
+ sql "DELETE FROM schema_version WHERE version_int = '23';"
+}
+
# TODO ... put functions here
# echo "db version = "${DATABASE_VER_NUM}
lvirt_module = None
def __init__(self, name, host, user, db, db_lock, test, image_path, host_id, version, develop_mode,
- develop_bridge_iface, password=None, keyfile = None, logger_name=None, debug=None):
+ develop_bridge_iface, password=None, keyfile = None, logger_name=None, debug=None, hypervisors=None):
"""Init a thread to communicate with compute node or ovs_controller.
:param host_id: host identity
:param name: name of the thread
self.pending_terminate_server =[] #list with pairs (time,server_uuid) time to send a terminate for a server being destroyed
self.next_update_server_status = 0 #time when must be check servers status
+####### self.hypervisor = "kvm" #hypervisor flag (default: kvm)
+ if hypervisors:
+ self.hypervisors = hypervisors
+ else:
+ self.hypervisors = "kvm"
+
+ self.xen_hyp = True if "xen" in self.hypervisors else False
+
self.hostinfo = None
self.queueLock = threading.Lock()
self.run_command_session = None
self.error = None
self.localhost = True if host == 'localhost' else False
- self.lvirt_conn_uri = "qemu+ssh://{user}@{host}/system?no_tty=1&no_verify=1".format(
- user=self.user, host=self.host)
+
+ if self.xen_hyp:
+ self.lvirt_conn_uri = "xen+ssh://{user}@{host}/?no_tty=1&no_verify=1".format(
+ user=self.user, host=self.host)
+ else:
+ self.lvirt_conn_uri = "qemu+ssh://{user}@{host}/system?no_tty=1&no_verify=1".format(
+ user=self.user, host=self.host)
if keyfile:
self.lvirt_conn_uri += "&keyfile=" + keyfile
+
self.remote_ip = None
self.local_ip = None
bus_ide = True if bus=='ide' else False
self.xml_level = 0
+ hypervisor = server.get('hypervisor', 'kvm')
+ os_type_img = server.get('os_image_type', 'other')
- text = "<domain type='kvm'>"
+ if hypervisor[:3] == 'xen':
+ text = "<domain type='xen'>"
+ else:
+ text = "<domain type='kvm'>"
#get topology
topo = server_metadata.get('topology', None)
if topo == None and 'metadata' in dev_list[0]:
if dev['type']=='cdrom' :
boot_cdrom = True
break
- text += self.tab()+ '<os>' + \
- self.inc_tab() + "<type arch='x86_64' machine='pc'>hvm</type>"
- if boot_cdrom:
- text += self.tab() + "<boot dev='cdrom'/>"
- text += self.tab() + "<boot dev='hd'/>" + \
- self.dec_tab()+'</os>'
+ if hypervisor == 'xenhvm':
+ text += self.tab()+ '<os>' + \
+ self.inc_tab() + "<type arch='x86_64' machine='xenfv'>hvm</type>"
+ text += self.tab() + "<loader type='rom'>/usr/lib/xen/boot/hvmloader</loader>"
+ if boot_cdrom:
+ text += self.tab() + "<boot dev='cdrom'/>"
+ text += self.tab() + "<boot dev='hd'/>" + \
+ self.dec_tab()+'</os>'
+ elif hypervisor == 'xen-unik':
+ text += self.tab()+ '<os>' + \
+ self.inc_tab() + "<type arch='x86_64' machine='xenpv'>xen</type>"
+ text += self.tab() + "<kernel>" + str(dev_list[0]['source file']) + "</kernel>" + \
+ self.dec_tab()+'</os>'
+ else:
+ text += self.tab()+ '<os>' + \
+ self.inc_tab() + "<type arch='x86_64' machine='pc'>hvm</type>"
+ if boot_cdrom:
+ text += self.tab() + "<boot dev='cdrom'/>"
+ text += self.tab() + "<boot dev='hd'/>" + \
+ self.dec_tab()+'</os>'
#features
text += self.tab()+'<features>'+\
self.inc_tab()+'<acpi/>' +\
self.tab() + "<on_poweroff>preserve</on_poweroff>" + \
self.tab() + "<on_reboot>restart</on_reboot>" + \
self.tab() + "<on_crash>restart</on_crash>"
- text += self.tab() + "<devices>" + \
- self.inc_tab() + "<emulator>/usr/libexec/qemu-kvm</emulator>" + \
- self.tab() + "<serial type='pty'>" +\
- self.inc_tab() + "<target port='0'/>" + \
- self.dec_tab() + "</serial>" +\
- self.tab() + "<console type='pty'>" + \
- self.inc_tab()+ "<target type='serial' port='0'/>" + \
- self.dec_tab()+'</console>'
+ if hypervisor == 'xenhvm':
+ text += self.tab() + "<devices>" + \
+ self.inc_tab() + "<emulator>/usr/bin/qemu-system-i386</emulator>" + \
+ self.tab() + "<serial type='pty'>" +\
+ self.inc_tab() + "<target port='0'/>" + \
+ self.dec_tab() + "</serial>" +\
+ self.tab() + "<console type='pty'>" + \
+ self.inc_tab()+ "<target type='serial' port='0'/>" + \
+ self.dec_tab()+'</console>' #In some libvirt version may be: <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> (depends on distro)
+ elif hypervisor == 'xen-unik':
+ text += self.tab() + "<devices>" + \
+ self.tab() + "<console type='pty'>" + \
+ self.inc_tab()+ "<target type='xen' port='0'/>" + \
+ self.dec_tab()+'</console>'
+ else:
+ text += self.tab() + "<devices>" + \
+ self.inc_tab() + "<emulator>/usr/libexec/qemu-kvm</emulator>" + \
+ self.tab() + "<serial type='pty'>" +\
+ self.inc_tab() + "<target port='0'/>" + \
+ self.dec_tab() + "</serial>" +\
+ self.tab() + "<console type='pty'>" + \
+ self.inc_tab()+ "<target type='serial' port='0'/>" + \
+ self.dec_tab()+'</console>'
if windows_os:
text += self.tab() + "<controller type='usb' index='0'/>" + \
self.tab() + "<controller type='ide' index='0'/>" + \
self.dec_tab() + "</video>" + \
self.tab() + "<memballoon model='virtio'/>" + \
self.tab() + "<input type='tablet' bus='usb'/>" #TODO revisar
+ elif hypervisor == 'xen-unik':
+ pass
+ else:
+ text += self.tab() + "<controller type='ide' index='0'/>" + \
+ self.tab() + "<input type='mouse' bus='ps2'/>" + \
+ self.tab() + "<input type='keyboard' bus='ps2'/>" + \
+ self.tab() + "<video>" + \
+ self.inc_tab() + "<model type='cirrus' vram='9216' heads='1'/>" + \
+ self.dec_tab() + "</video>"
#> self.tab()+'<alias name=\'hostdev0\'/>\n' +\
#> self.dec_tab()+'</hostdev>\n' +\
vd_index = 'a'
for dev in dev_list:
bus_ide_dev = bus_ide
- if dev['type']=='cdrom' or dev['type']=='disk':
+ if (dev['type']=='cdrom' or dev['type']=='disk') and hypervisor != 'xen-unik':
if dev['type']=='cdrom':
bus_ide_dev = True
text += self.tab() + "<disk type='file' device='"+dev['type']+"'>"
dev_text = dev_text.replace('__dev__', vd_index)
vd_index = chr(ord(vd_index)+1)
text += dev_text
+ elif hypervisor == 'xen-unik':
+ pass
else:
return -1, 'Unknown device type ' + dev['type']
vlan = content[0]['provider'].replace('OVS:', '')
text += self.tab() + "<interface type='bridge'>" + \
self.inc_tab() + "<source bridge='ovim-" + str(vlan) + "'/>"
+ if hypervisor == 'xenhvm' or hypervisor == 'xen-unik':
+ text += self.tab() + "<script path='vif-openvswitch'/>"
else:
return -1, 'Unknown Bridge net provider ' + content[0]['provider']
if model!=None:
self.logger.error("launch_server ERROR getting server from DB %d %s", result, server_data)
return result, server_data
+ self.hypervisor = str(server_data['hypervisor'])
+
#0: get image metadata
server_metadata = server.get('metadata', {})
use_incremental = None
if "use_incremental" in server_metadata:
use_incremental = False if server_metadata["use_incremental"] == "no" else True
+ if self.xen_hyp == True:
+ use_incremental = False
server_host_files = self.localinfo['server_files'].get( server['uuid'], {})
if rebuild:
elif requirements['vcpus']==0:
return (-1, "Processor information not set neither at extended field not at vcpus")
+ if 'hypervisor' in server: requirements['hypervisor'] = server['hypervisor'] #Unikernels extension
db_lock.acquire()
result, content = db.get_numas(requirements, server.get('host_id', None), only_of_ports)
if 'description' in server: resources['description'] = server['description']
if 'name' in server: resources['name'] = server['name']
+ if 'hypervisor' in server: resources['hypervisor'] = server['hypervisor']
+ if 'os_image_type' in server: resources['os_image_type'] = server['os_image_type']
resources['extended'] = {} #optional
resources['extended']['numas'] = []
http2db_tenant={'id':'uuid'}
http2db_flavor={'id':'uuid','imageRef':'image_id', 'size': 'image_size'}
http2db_image={'id':'uuid', 'created':'created_at', 'updated':'modified_at', 'public': 'public'}
-http2db_server={'id':'uuid','hostId':'host_id','flavorRef':'flavor_id','imageRef':'image_id','created':'created_at'}
+http2db_server={'id':'uuid','hostId':'host_id','flavorRef':'flavor_id','osImageType':'os_image_type','imageRef':'image_id','created':'created_at'} #Unikernels extension
http2db_network={'id':'uuid','provider:vlan':'vlan', 'provider:physical': 'provider'}
http2db_ofc = {'id': 'uuid'}
http2db_port={'id':'uuid', 'network_id':'net_id', 'mac_address':'mac', 'device_owner':'type','device_id':'instance_id','binding:switch_port':'switch_port','binding:vlan':'vlan', 'bandwidth':'Mbps'}
def get_hosts():
select_, where_, limit_ = filter_query_string(bottle.request.query, http2db_host,
- ('id', 'name', 'description', 'status', 'admin_state_up', 'ip_name'))
+ ('id', 'name', 'description', 'status', 'admin_state_up', 'ip_name', 'hypervisors')) #Unikernels extension
myself = config_dic['http_threads'][ threading.current_thread().name ]
result, content = myself.db.get_table(FROM='hosts', SELECT=select_, WHERE=where_, LIMIT=limit_)
db=config_dic['db'], db_lock=config_dic['db_lock'],
test=host_test_mode, image_path=config_dic['host_image_path'],
version=config_dic['version'], host_id=content['uuid'],
- develop_mode=host_develop_mode, develop_bridge_iface=host_develop_bridge_iface)
+ develop_mode=host_develop_mode, develop_bridge_iface=host_develop_bridge_iface,
+ hypervisors=host.get('hypervisors', None)) #Unikernels extension
thread.start()
config_dic['host_threads'][content['uuid']] = thread
__author__ = "Alfonso Tierno, Leonardo Mirabal"
__date__ = "$06-Feb-2017 12:07:15$"
-__version__ = "0.5.24-r540"
+__version__ = "0.5.24-r542"
version_date = "Mar 2018"
-database_version = 22 #needed database schema version
+database_version = 23 #needed database schema version
HTTP_Bad_Request = 400
HTTP_Unauthorized = 401
host_develop_bridge_iface = self.config.get('development_bridge', None)
# get host list from data base before starting threads
- r, hosts = self.db.get_table(SELECT=('name', 'ip_name', 'user', 'uuid', 'password', 'keyfile'),
- FROM='hosts', WHERE={'status': 'ok'})
+ r, hosts = self.db.get_table(SELECT=('name', 'ip_name', 'user', 'uuid', 'hypervisors', 'password', 'keyfile'),
+ FROM='hosts', WHERE={'status': 'ok'}) #Unikernels extension
if r < 0:
raise ovimException("Cannot get hosts from database {}".format(hosts))
version=self.config['version'], host_id=host['uuid'],
develop_mode=host_develop_mode,
develop_bridge_iface=host_develop_bridge_iface,
+ hypervisors=host['hypervisors'], #Unikernels extension
logger_name=self.logger_name + ".host." + host['name'],
debug=self.config.get('log_level_host'))
w = sql_dict.get('WHERE')
if w:
where_and = " AND ".join(map( lambda x: str(x) + (" is Null" if w[x] is None else "='"+str(w[x])+"'"), w.keys()) )
+ w = sql_dict.get('WHERE_LIKE') #Unikernels extension -START-
+ if w:
+ where_and_like = " AND ".join(map( lambda x: str(x) + (" is Null" if w[x] is None else " LIKE '"+str(w[x])+"'"), w.keys()) )
+ if where_and:
+ where_and += " AND " + where_and_like
+ else:
+ where_and = where_and_like #Unikernels extension -END-
w = sql_dict.get('WHERE_NOT')
if w:
where_and_not = " AND ".join(map( lambda x: str(x) + (" is not Null" if w[x] is None else "!='"+str(w[x])+"'"), w.keys()) )
with self.con:
self.cur = self.con.cursor(mdb.cursors.DictCursor)
#get HOST
- cmd = "SELECT uuid, user, password, keyfile, name, ip_name, description, ranking, admin_state_up, "\
+ cmd = "SELECT uuid, user, password, keyfile, name, ip_name, description, hypervisors, ranking, admin_state_up, "\
"DATE_FORMAT(created_at,'%Y-%m-%dT%H:%i:%s') as created_at "\
- "FROM hosts WHERE " + where_filter
+ "FROM hosts WHERE " + where_filter #Unikernels extension
self.logger.debug(cmd)
self.cur.execute(cmd)
if self.cur.rowcount == 0:
with self.con:
self.cur = self.con.cursor(mdb.cursors.DictCursor)
#get INSTANCE
- cmd = "SELECT uuid, name, description, progress, host_id, flavor_id, image_id, status, last_error, "\
- "tenant_id, ram, vcpus, created_at FROM instances WHERE uuid='{}'".format(instance_id)
+ cmd = "SELECT uuid, name, description, progress, host_id, flavor_id, image_id, status, hypervisor, os_image_type, last_error, "\
+ "tenant_id, ram, vcpus, created_at FROM instances WHERE uuid='{}'".format(instance_id) #Unikernels extension
self.logger.debug(cmd)
self.cur.execute(cmd)
if self.cur.rowcount == 0 : return 0, "instance '" + str(instance_id) +"'not found."
#self.logger.debug(error_text)
return -1, error_text
+ if not 'hypervisor' in requirements: #Unikernels extension -END-
+ requirements['hypervisor'] = "kvm"
+ for valid_host in valid_hosts:
+ if not 'hypervisors' in valid_host:
+ valid_host['hypervisors'] = "kvm"
+
+ valid_hosts = tuple(valid_host for valid_host in valid_hosts if requirements['hypervisor'] in valid_host['hypervisors'].split(","))
+
+ if len(valid_hosts)<=0:
+ error_text = 'No room at data center. Cannot find a host with %s hypervisor or not have enough resources available' % (str(requirements['hypervisor']))
+ #self.logger.debug(error_text)
+ return -1, error_text #Unikernels extension -END-
+
#elif req_numa != None:
#Find valid numa nodes for memory requirements
self.cur = self.con.cursor(mdb.cursors.DictCursor)
"features": description_schema,
"ranking": integer0_schema,
"autodiscover": {"type": "boolean"}, # try to discover host parameters instead of providing in this schema
+ "hypervisors": description_schema, #Unikernels extension
"devices": {
"type": "array",
"items": {
"hostId":id_schema,
"flavorRef":id_schema,
"imageRef":id_schema,
+ "hypervisor":{"type":"string", "enum":["kvm","xen-unik","xenhvm"]}, #Unikernels extension
+ "osImageType":{"type":"string", "enum":["clickos","other"]}, #Unikernels extension
"extended": extended_schema,
"networks":networks_schema
},