import imp
from vim_schema import localinfo_schema, hostinfo_schema
import random
-#from logging import Logger
-#import auxiliary_functions as af
+import os
-#TODO: insert a logging system
+# from logging import Logger
+# import auxiliary_functions as af
-#global lvirt_module
-#lvirt_module=None #libvirt module is charged only if not in test mode
+# TODO: insert a logging system
+
+
+# global lvirt_module
+# lvirt_module=None #libvirt module is charged only if not in test mode
class host_thread(threading.Thread):
lvirt_module = None
- def __init__(self, name, host, user, db, db_lock, test, image_path, host_id, version, develop_mode, develop_bridge_iface):
+
+ def __init__(self, name, host, user, db, db_lock, test, image_path, host_id, version, develop_mode,
+ develop_bridge_iface):
'''Init a thread.
- Arguments:
+ Arguments:
'id' number of thead
'name' name of thread
'host','user': host ip or name to manage and user
:return:
"""
- command = 'sudo ovs-vsctl del-port br-int ovim-' + vlan
+ if self.test:
+ return
+
+ port_name = 'ovim-' + vlan
+ command = 'sudo ovs-vsctl del-port br-int ' + port_name
print self.name, ': command:', command
(_, stdout, _) = self.ssh_conn.exec_command(command)
content = stdout.read()
else:
return False
- def is_port_free(self, vlan, net_uuid):
+ def delete_dhcp_server(self, vlan, net_uuid, dhcp_path):
+ """
+ Delete dhcp server process lining in namespace
+ :param vlan: segmentation id
+ :param net_uuid: network uuid
+ :param dhcp_path: conf fiel path that live in namespace side
+ :return:
+ """
+ if self.test:
+ return
+ if not self.is_dhcp_port_free(vlan, net_uuid):
+ return True
+
+ net_namespace = 'ovim-' + vlan
+ dhcp_path = os.path.join(dhcp_path, net_namespace)
+ pid_file = os.path.join(dhcp_path, 'dnsmasq.pid')
+
+ command = 'sudo ip netns exec ' + net_namespace + ' cat ' + pid_file
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip netns exec ' + net_namespace + ' kill -9 ' + content
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ # if len(content) == 0:
+ # return True
+ # else:
+ # return False
+
+ def is_dhcp_port_free(self, host_id, net_uuid):
+ """
+ Check if any port attached to the a net in a vxlan mesh across computes nodes
+ :param host_id: host id
+ :param net_uuid: network id
+ :return: True if is not free
+ """
+ self.db_lock.acquire()
+ result, content = self.db.get_table(
+ FROM='ports',
+ WHERE={'p.type': 'instance:ovs', 'p.net_id': net_uuid}
+ )
+ self.db_lock.release()
+
+ if len(content) > 0:
+ return False
+ else:
+ return True
+
+ def is_port_free(self, host_id, net_uuid):
"""
Check if there not ovs ports of a network in a compute host.
- :param vlan: vlan port id
+ :param host_id: host id
:param net_uuid: network id
:return: True if is not free
"""
+
self.db_lock.acquire()
result, content = self.db.get_table(
FROM='ports as p join instances as i on p.instance_id=i.uuid',
- WHERE={"i.host_id": self.host_id, 'p.type': 'instance:ovs', 'p.net_id': net_uuid}
+ WHERE={"i.host_id": self.host_id, 'p.type': 'instance:ovs', 'p.net_id': net_uuid}
)
self.db_lock.release()
- if content > 0:
+ if len(content) > 0:
return False
else:
return True
"""
Add a bridge linux as a port to a OVS bridge and set a vlan for an specific linux bridge
:param vlan: vlan port id
- :return:
+ :return: True if success
"""
- command = 'sudo ovs-vsctl add-port br-int ovim-' + vlan + ' tag=' + vlan
+
+ if self.test:
+ return
+
+ port_name = 'ovim-' + vlan
+ command = 'sudo ovs-vsctl add-port br-int ' + port_name + ' tag=' + vlan
print self.name, ': command:', command
(_, stdout, _) = self.ssh_conn.exec_command(command)
content = stdout.read()
else:
return False
+ def delete_dhcp_port(self, vlan, net_uuid):
+ """
+ Delete from an existing OVS bridge a linux bridge port attached and the linux bridge itself.
+ :param vlan: segmentation id
+ :param net_uuid: network id
+ :return: True if success
+ """
+
+ if self.test:
+ return
+
+ if not self.is_dhcp_port_free(vlan, net_uuid):
+ return True
+ self.delete_dhcp_interfaces(vlan)
+ return True
+
def delete_bridge_port_attached_to_ovs(self, vlan, net_uuid):
"""
Delete from an existing OVS bridge a linux bridge port attached and the linux bridge itself.
"""
if self.test:
return
+
if not self.is_port_free(vlan, net_uuid):
return True
self.delete_port_to_ovs_bridge(vlan, net_uuid)
self.delete_linux_bridge(vlan)
- return True
+ return True
def delete_linux_bridge(self, vlan):
"""
:param vlan: vlan port id
:return: True if success
"""
- command = 'sudo ifconfig ovim-' + vlan + ' down && sudo brctl delbr ovim-' + vlan
+
+ if self.test:
+ return
+
+ port_name = 'ovim-' + vlan
+ command = 'sudo ip link set dev veth0-' + vlan + ' down'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+ #
+ # if len(content) != 0:
+ # return False
+
+ command = 'sudo ifconfig ' + port_name + ' down && sudo brctl delbr ' + port_name
print self.name, ': command:', command
(_, stdout, _) = self.ssh_conn.exec_command(command)
content = stdout.read()
:param vlan: netowrk vlan id
:return:
"""
- command = 'sudo brctl addbr ovim-' + vlan + ' && sudo ifconfig ovim-' + vlan + ' up'
+
+ if self.test:
+ return
+
+ port_name = 'ovim-' + vlan
+ command = 'sudo brctl show | grep ' + port_name
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ # if exist nothing to create
+ # if len(content) == 0:
+ # return False
+
+ command = 'sudo brctl addbr ' + port_name
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ # if len(content) == 0:
+ # return True
+ # else:
+ # return False
+
+ command = 'sudo brctl stp ' + port_name + ' on'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ # if len(content) == 0:
+ # return True
+ # else:
+ # return False
+ command = 'sudo ip link set dev ' + port_name + ' up'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ if len(content) == 0:
+ return True
+ else:
+ return False
+
+ def set_mac_dhcp_server(self, ip, mac, vlan, netmask, dhcp_path):
+ """
+ Write into dhcp conf file a rule to assigned a fixed ip given to an specific MAC address
+ :param ip: IP address asigned to a VM
+ :param mac: VM vnic mac to be macthed with the IP received
+ :param vlan: Segmentation id
+ :param netmask: netmask value
+ :param path: dhcp conf file path that live in namespace side
+ :return: True if success
+ """
+
+ if self.test:
+ return
+
+ net_namespace = 'ovim-' + vlan
+ dhcp_path = os.path.join(dhcp_path, net_namespace)
+ dhcp_hostsdir = os.path.join(dhcp_path, net_namespace)
+
+ if not ip:
+ return False
+
+ ip_data = mac.upper() + ',' + ip
+
+ command = 'sudo ip netns exec ' + net_namespace + ' touch ' + dhcp_hostsdir
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip netns exec ' + net_namespace + ' sudo bash -ec "echo ' + ip_data + ' >> ' + dhcp_hostsdir + '"'
+
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ if len(content) == 0:
+ return True
+ else:
+ return False
+
+ def delete_mac_dhcp_server(self, ip, mac, vlan, dhcp_path):
+ """
+ Delete into dhcp conf file the ip assigned to a specific MAC address
+
+ :param ip: IP address asigned to a VM
+ :param mac: VM vnic mac to be macthed with the IP received
+ :param vlan: Segmentation id
+ :param dhcp_path: dhcp conf file path that live in namespace side
+ :return:
+ """
+
+ if self.test:
+ return
+
+ net_namespace = 'ovim-' + vlan
+ dhcp_path = os.path.join(dhcp_path, net_namespace)
+ dhcp_hostsdir = os.path.join(dhcp_path, net_namespace)
+
+ if not ip:
+ return False
+
+ ip_data = mac.upper() + ',' + ip
+
+ command = 'sudo ip netns exec ' + net_namespace + ' sudo sed -i \'/' + ip_data + '/d\' ' + dhcp_hostsdir
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ if len(content) == 0:
+ return True
+ else:
+ return False
+
+ def launch_dhcp_server(self, vlan, ip_range, netmask, dhcp_path):
+ """
+ Generate a linux bridge and attache the port to a OVS bridge
+ :param self:
+ :param vlan: Segmentation id
+ :param ip_range: IP dhcp range
+ :param netmask: network netmask
+ :param dhcp_path: dhcp conf file path that live in namespace side
+ :return: True if success
+ """
+
+ if self.test:
+ return
+
+ interface = 'tap-' + vlan
+ net_namespace = 'ovim-' + vlan
+ dhcp_path = os.path.join(dhcp_path, net_namespace)
+ leases_path = os.path.join(dhcp_path, "dnsmasq.leases")
+ pid_file = os.path.join(dhcp_path, 'dnsmasq.pid')
+
+ dhcp_range = ip_range[0] + ',' + ip_range[1] + ',' + netmask
+
+ command = 'sudo ip netns exec ' + net_namespace + ' mkdir -p ' + dhcp_path
print self.name, ': command:', command
(_, stdout, _) = self.ssh_conn.exec_command(command)
content = stdout.read()
- if len(content) != 0:
+ pid_path = os.path.join(dhcp_path, 'dnsmasq.pid')
+ command = 'sudo ip netns exec ' + net_namespace + ' cat ' + pid_path
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+ # check if pid is runing
+ pid_status_path = content
+ if content:
+ command = "ps aux | awk '{print $2 }' | grep " + pid_status_path
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+ if not content:
+ command = 'sudo ip netns exec ' + net_namespace + ' /usr/sbin/dnsmasq --strict-order --except-interface=lo ' \
+ '--interface=' + interface + ' --bind-interfaces --dhcp-hostsdir=' + dhcp_path + \
+ ' --dhcp-range ' + dhcp_range + ' --pid-file=' + pid_file + ' --dhcp-leasefile=' + leases_path + ' --listen-address ' + ip_range[0]
+
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.readline()
+
+ if len(content) == 0:
+ return True
+ else:
return False
- command = 'sudo brctl stp ovim-' + vlan + ' on'
+ def delete_dhcp_interfaces(self, vlan):
+ """
+ Create a linux bridge with STP active
+ :param vlan: netowrk vlan id
+ :return:
+ """
+
+ if self.test:
+ return
+
+ net_namespace = 'ovim-' + vlan
+ command = 'sudo ovs-vsctl del-port br-int ovs-tap-' + vlan
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip netns exec ' + net_namespace + ' ip link set dev tap-' + vlan + ' down'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip link set dev ovs-tap-' + vlan + ' down'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ def create_dhcp_interfaces(self, vlan, ip, netmask):
+ """
+ Create a linux bridge with STP active
+ :param vlan: segmentation id
+ :param ip: Ip included in the dhcp range for the tap interface living in namesapce side
+ :param netmask: dhcp net CIDR
+ :return: True if success
+ """
+
+ if self.test:
+ return
+
+ net_namespace = 'ovim-' + vlan
+ namespace_interface = 'tap-' + vlan
+
+ command = 'sudo ip netns add ' + net_namespace
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip link add tap-' + vlan + ' type veth peer name ovs-tap-' + vlan
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ovs-vsctl add-port br-int ovs-tap-' + vlan + ' tag=' + vlan
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip link set tap-' + vlan + ' netns ' + net_namespace
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip netns exec ' + net_namespace + ' ip link set dev tap-' + vlan + ' up'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip link set dev ovs-tap-' + vlan + ' up'
+ print self.name, ': command:', command
+ (_, stdout, _) = self.ssh_conn.exec_command(command)
+ content = stdout.read()
+
+ command = 'sudo ip netns exec ' + net_namespace + ' ' + ' ifconfig ' + namespace_interface \
+ + ' ' + ip + ' netmask ' + netmask
print self.name, ': command:', command
(_, stdout, _) = self.ssh_conn.exec_command(command)
content = stdout.read()
continue
self.db_lock.acquire()
- result, content = self.db.get_table(FROM='images', SELECT=('path','metadata'),WHERE={'uuid':dev['image_id']} )
+ result, content = self.db.get_table(FROM='images', SELECT=('path', 'metadata'),
+ WHERE={'uuid': dev['image_id']})
self.db_lock.release()
if result <= 0:
error_text = "ERROR", result, content, "when getting image", dev['image_id']
finally:
if conn is not None: conn.close()
-
-
+
+
def create_server(server, db, db_lock, only_of_ports):
#print "server"
#print "server"
control_iface['net_id']=control_iface.pop('uuid')
#Get the brifge name
db_lock.acquire()
- result, content = db.get_table(FROM = 'nets',
- SELECT = ('name','type', 'vlan', 'provider'),
- WHERE = {'uuid':control_iface['net_id']})
+ result, content = db.get_table(FROM='nets',
+ SELECT=('name', 'type', 'vlan', 'provider', 'enable_dhcp',
+ 'dhcp_first_ip', 'dhcp_last_ip', 'cidr'),
+ WHERE={'uuid': control_iface['net_id']})
db_lock.release()
if result < 0:
pass
control_iface["type"] = "instance:bridge"
if network.get("vlan"):
control_iface["vlan"] = network["vlan"]
+
+ if network.get("enable_dhcp") == 'true':
+ control_iface["enable_dhcp"] = network.get("enable_dhcp")
+ control_iface["dhcp_first_ip"] = network["dhcp_first_ip"]
+ control_iface["dhcp_last_ip"] = network["dhcp_last_ip"]
+ control_iface["cidr"] = network["cidr"]
else:
if network['type']!='data' and network['type']!='ptp':
return -1, "Error at field netwoks: network uuid %s for dataplane interface is not of type data or ptp" % control_iface['net_id']
import hashlib
import os
import imp
+from netaddr import IPNetwork, IPAddress, all_matching_cidrs
#import only if needed because not needed in test mode. To allow an easier installation import RADclass
from jsonschema import validate as js_v, exceptions as js_e
import host_thread as ht
if config_dic['network_type'] == 'ovs':
# create bridge
+ create_dhcp_ovs_bridge()
config_dic['host_threads'][content['uuid']].insert_task("new-ovsbridge")
# check if more host exist
create_vxlan_mesh(content['uuid'])
return
+def get_dhcp_controller():
+ """
+ Create an host_thread object for manage openvim controller and not create a thread for itself
+ :return: dhcp_host openvim controller object
+ """
+
+ if 'openvim_controller' in config_dic['host_threads']:
+ return config_dic['host_threads']['openvim_controller']
+
+ bridge_ifaces = []
+ controller_ip = config_dic['ovs_controller_ip']
+ ovs_controller_user = config_dic['ovs_controller_user']
+
+ host_test_mode = True if config_dic['mode'] == 'test' or config_dic['mode'] == "OF only" else False
+ host_develop_mode = True if config_dic['mode'] == 'development' else False
+
+ dhcp_host = ht.host_thread(name='openvim_controller', user=ovs_controller_user, host=controller_ip, db=config_dic['db'],
+ db_lock=config_dic['db_lock'], test=host_test_mode,
+ image_path=config_dic['image_path'], version=config_dic['version'],
+ host_id='openvim_controller', develop_mode=host_develop_mode,
+ develop_bridge_iface=bridge_ifaces)
+
+ config_dic['host_threads']['openvim_controller'] = dhcp_host
+ dhcp_host.ssh_connect()
+ return dhcp_host
+
+
+def delete_dhcp_ovs_bridge(vlan, net_uuid):
+ """
+ Delete bridges and port created during dhcp launching at openvim controller
+ :param vlan: net vlan id
+ :param net_uuid: network identifier
+ :return:
+ """
+ dhcp_path = config_dic['ovs_controller_file_path']
+
+ controller_host = get_dhcp_controller()
+ controller_host.delete_dhcp_port(vlan, net_uuid)
+ controller_host.delete_dhcp_server(vlan, net_uuid, dhcp_path)
+
+
+def create_dhcp_ovs_bridge():
+ """
+ Initialize bridge to allocate the dhcp server at openvim controller
+ :return:
+ """
+ controller_host = get_dhcp_controller()
+ controller_host.create_ovs_bridge()
+
+
+def set_mac_dhcp(vm_ip, vlan, first_ip, last_ip, cidr, mac):
+ """"
+ Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
+ :param vm_ip: IP address asigned to a VM
+ :param vlan: Segmentation id
+ :param first_ip: First dhcp range ip
+ :param last_ip: Last dhcp range ip
+ :param cidr: net cidr
+ :param mac: VM vnic mac to be macthed with the IP received
+ """
+ if not vm_ip:
+ return
+ ip_tools = IPNetwork(cidr)
+ cidr_len = ip_tools.prefixlen
+ dhcp_netmask = str(ip_tools.netmask)
+ dhcp_path = config_dic['ovs_controller_file_path']
+
+ new_cidr = [first_ip + '/' + str(cidr_len)]
+ if not len(all_matching_cidrs(vm_ip, new_cidr)):
+ vm_ip = None
+
+ controller_host = get_dhcp_controller()
+ controller_host.set_mac_dhcp_server(vm_ip, mac, vlan, dhcp_netmask, dhcp_path)
+
+
+def delete_mac_dhcp(vm_ip, vlan, mac):
+ """
+ Delete into dhcp conf file the ip assigned to a specific MAC address
+ :param vm_ip: IP address asigned to a VM
+ :param vlan: Segmentation id
+ :param mac: VM vnic mac to be macthed with the IP received
+ :return:
+ """
+
+ dhcp_path = config_dic['ovs_controller_file_path']
+
+ controller_host = get_dhcp_controller()
+ controller_host.delete_mac_dhcp_server(vm_ip, mac, vlan, dhcp_path)
+
+
+def launch_dhcp_server(vlan, first_ip, last_ip, cidr):
+ """
+ Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
+ :param vlan: vlan identifier
+ :param first_ip: First dhcp range ip
+ :param last_ip: Last dhcp range ip
+ :param cidr: net cidr
+ :return:
+ """
+ ip_tools = IPNetwork(cidr)
+ dhcp_netmask = str(ip_tools.netmask)
+ ip_range = [first_ip, last_ip]
+ dhcp_path = config_dic['ovs_controller_file_path']
+
+ controller_host = get_dhcp_controller()
+ controller_host.create_linux_bridge(vlan)
+ controller_host.create_dhcp_interfaces(vlan, first_ip, dhcp_netmask)
+ controller_host.launch_dhcp_server(vlan, ip_range, dhcp_netmask, dhcp_path)
+
+
def create_vxlan_mesh(host_id):
+ """
+ Create vxlan mesh across all openvimc controller and computes.
+ :param host_id: host identifier
+ :param host_id: host identifier
+ :return:
+ """
+ dhcp_compute_name = get_vxlan_interface("dhcp")
existing_hosts = get_hosts()
- if len(existing_hosts['hosts']) > 1:
+ if len(existing_hosts['hosts']) > 0:
+ # vlxan mesh creation between openvim controller and computes
computes_available = existing_hosts['hosts']
+ controller_host = get_dhcp_controller()
+ for compute in computes_available:
+ vxlan_interface_name = get_vxlan_interface(compute['id'][:8])
+ config_dic['host_threads'][compute['id']].insert_task("new-vxlan", dhcp_compute_name, controller_host.host)
+ controller_host.create_ovs_vxlan_tunnel(vxlan_interface_name, compute['ip_name'])
- # TUNEL openvim controller
-
+ # vlxan mesh creation between openvim computes
for count, compute_owner in enumerate(computes_available):
for compute in computes_available:
if compute_owner['id'] == compute['id']:
pass
else:
vxlan_interface_name = get_vxlan_interface(compute_owner['id'][:8])
+ controller_host.create_ovs_vxlan_tunnel(vxlan_interface_name, compute_owner['ip_name'])
config_dic['host_threads'][compute['id']].insert_task("new-vxlan",
vxlan_interface_name,
compute_owner['ip_name'])
"""
existing_hosts = get_hosts()
computes_available = existing_hosts['hosts']
+ #
vxlan_interface_name = get_vxlan_interface(host_id[:8])
-
+ controller_host = get_dhcp_controller()
+ controller_host.delete_ovs_vxlan_tunnel(vxlan_interface_name)
+ # remove bridge from openvim controller if no more computes exist
+ if len(existing_hosts):
+ controller_host.delete_ovs_bridge()
+ # Remove vxlan mesh
for compute in computes_available:
if host_id == compute['id']:
pass
else:
- config_dic['host_threads'][compute['id']].insert_task("del-vxlan",vxlan_interface_name)
+ controller_host.delete_ovs_vxlan_tunnel(vxlan_interface_name)
+ config_dic['host_threads'][compute['id']].insert_task("del-vxlan", vxlan_interface_name)
def get_vxlan_interface(local_uuid):
print
if server_start == 'no':
content['status'] = 'INACTIVE'
+ dhcp_nets_id = []
+ for net in http_content['server']['networks']:
+ if net['type'] == 'instance:ovs':
+ dhcp_nets_id.append(get_network_id(net['net_id']))
+
ports_to_free=[]
new_instance_result, new_instance = my.db.new_instance(content, nets, ports_to_free)
if new_instance_result < 0:
print ':http_post_servers ERROR UPDATING NETS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + c
-
- #look for dhcp ip address
- r2, c2 = my.db.get_table(FROM="ports", SELECT=["mac", "net_id"], WHERE={"instance_id": new_instance})
+ #look for dhcp ip address
+ r2, c2 = my.db.get_table(FROM="ports", SELECT=["mac", "ip_address", "net_id"], WHERE={"instance_id": new_instance})
if r2 >0:
for iface in c2:
if config_dic.get("dhcp_server") and iface["net_id"] in config_dic["dhcp_nets"]:
server_net = get_network_id(iface['net_id'])
if server_net["network"].get('provider:physical', "")[:3] == 'OVS':
vlan = str(server_net['network']['provider:vlan'])
- config_dic['host_threads'][server['host_id']].insert_task("create-ovs-bridge-port", vlan)
+ dhcp_enable = bool(server_net['network']['enable_dhcp'])
+ if dhcp_enable:
+ dhcp_firt_ip = str(server_net['network']['dhcp_first_ip'])
+ dhcp_last_ip = str(server_net['network']['dhcp_last_ip'])
+ dhcp_cidr = str(server_net['network']['cidr'])
+ vm_dhcp_ip = c2[0]["ip_address"]
+ config_dic['host_threads'][server['host_id']].insert_task("create-ovs-bridge-port", vlan)
+
+ set_mac_dhcp(vm_dhcp_ip, vlan, dhcp_firt_ip, dhcp_last_ip, dhcp_cidr, c2[0]['mac'])
+ launch_dhcp_server(vlan, dhcp_firt_ip, dhcp_last_ip, dhcp_cidr)
+
#Start server
-
server['uuid'] = new_instance
server_start = server.get('start', 'yes')
if server_start != 'no':
- server['paused'] = True if server_start == 'paused' else False
+ server['paused'] = True if server_start == 'paused' else False
server['action'] = {"start":None}
server['status'] = "CREATING"
#Program task
print ':http_post_servers ERROR UPDATING dhcp_server !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + c
# delete ovs-port and linux bridge, contains a list of tuple (net_id,vlan)
for net in net_ovs_list:
+ mac = str(net[3])
+ vm_ip = str(net[2])
vlan = str(net[1])
net_id = net[0]
+ delete_dhcp_ovs_bridge(vlan, net_id)
+ delete_mac_dhcp(vm_ip, vlan, mac)
config_dic['host_threads'][server['host_id']].insert_task('del-ovs-port', vlan, net_id)
return format_out(data)
print "http_get_networks error %d %s" % (result, content)
bottle.abort(-result, content)
else:
- convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp') )
+ convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
delete_nulls(content)
change_keys_http2db(content, http2db_network, reverse=True)
data={'networks' : content}
print "http_get_networks_id network '%s' not found" % network_id
bottle.abort(HTTP_Not_Found, 'network %s not found' % network_id)
else:
- convert_boolean(content, ('shared', 'admin_state_up', 'enale_dhcp') )
+ convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
change_keys_http2db(content, http2db_network, reverse=True)
#get ports
result, ports = my.db.get_table(FROM='ports', SELECT=('uuid as port_id',),
#check valid params
net_provider = network.get('provider')
net_type = network.get('type')
+ net_type = network.get('type')
+ net_enable_dhcp = network.get('enable_dhcp')
+ if net_enable_dhcp:
+ net_cidr = network.get('cidr')
+
net_vlan = network.get("vlan")
net_bind_net = network.get("bind_net")
net_bind_type= network.get("bind_type")
network['provider'] = net_provider
network['type'] = net_type
network['vlan'] = net_vlan
+
+ if 'enable_dhcp' in network and network['enable_dhcp']:
+ check_dhcp_data_integrity(network)
+
result, content = my.db.new_row('nets', network, True, True)
if result >= 0:
if bridge_net!=None:
bridge_net[3] = content
-
if config_dic.get("dhcp_server") and config_dic['network_type'] == 'bridge':
if network["name"] in config_dic["dhcp_server"].get("nets", () ):
config_dic["dhcp_nets"].append(content)
return
+def check_dhcp_data_integrity(network):
+ """
+ Check if all dhcp parameter for anet are valid, if not will be calculated from cidr value
+ :param network: list with user nets paramters
+ :return:
+ """
+ control_iface = []
+
+ if "cidr" in network:
+ cidr = network["cidr"]
+
+ ips = IPNetwork(cidr)
+ if "dhcp_first_ip" not in network:
+ network["dhcp_first_ip"] = str(ips[2])
+ if "dhcp_last_ip" not in network:
+ network["dhcp_last_ip"] = str(ips[-2])
+
+
@bottle.route(url_base + '/networks/<network_id>', method='PUT')
def http_put_network_id(network_id):
'''update a network_id into the database.'''
bottle.abort(-result, content)
return
+
# - ovs : (by default) Use a vlxan mesh between computes to handle the network overlay.
# - bridge: Use pre-populated linux bridges with L2 conectivity at compte nodes.
network_type : ovs
+ovs_controller_ip : localhost # dhcp controller IP address, must be change in order to
+ovs_controller_user : "osm_dhcp" # User for the dchp controller for OVS networks
+ovs_controller_file_path : "/var/lib/openvim" # Path for dhcp daemon configuration, by default '/var/lib/openvim'
+
#host bridge interfaces for networks
# Apply only for 'network_type: bridge'
'log_level_of': 'ERROR',
'bridge_ifaces': {},
'network_type': 'ovs',
+ 'ovs_controller_user': 'osm_dhcp',
+ 'ovs_controller_file_path': '/var/lib/',
}
try:
#First load configuration from configuration file
( 'development_bridge' not in config_dic or config_dic['development_bridge'] not in config_dic.get("bridge_ifaces",None) ):
logger.error("'%s' is not a valid 'development_bridge', not one of the 'bridge_ifaces'", config_file)
exit(-1)
-
+
if config_dic['mode'] != 'normal':
print '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
print "!! Warning, openvimd in TEST mode '%s'" % config_dic['mode']
--- /dev/null
+#!/bin/bash
+##
+# This file is part of openvim
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+#
+# Authors: Leonardo Mirabal
+# February 2017
+
+
+
+function _usage(){
+ echo -e "Usage: sudo $0 <user-name> "
+ echo -e " Configure dhcp server for VIM usage. (version 1.0). Params:"
+ echo -e " <user-name> Create if not exist and configure this user for openvim to connect"
+ echo -e " -h --help this help"
+ exit 1
+}
+
+function _install_packages_dependencies()
+{
+ # Required packages by openvim
+ apt-get -y update
+ apt-get -y install ethtool build-essential dnsmasq openvswitch-switch
+ echo "Remove unneeded packages....."
+ apt-get -y autoremove
+}
+
+function _add_user_to_visudo()
+{
+# Allow admin users to access without password
+if ! grep -q "#openmano" /etc/sudoers
+then
+ cat >> /home/${option_user}/script_visudo.sh << EOL
+#!/bin/bash
+echo "#openmano allow to group admin to grant root privileges without password" >> \$1
+echo "${option_user} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+EOL
+ chmod +x /home/${option_user}/script_visudo.sh
+ echo "allowing admin user to get root privileges withut password"
+ export EDITOR=/home/${option_user}/script_visudo.sh && sudo -E visudo
+ rm -f /home/${option_user}/script_visudo.sh
+fi
+
+}
+
+function _create_ovs_controller_config_path() {
+ mkdir -p '/var/lib/openvim'
+}
+
+function _install_user() {
+ # create user given by the user and add to groups need it.
+ # Add required groups
+ groupadd -f admin
+
+ # Adds user, default password same as name
+ if grep -q "^${option_user}:" /etc/passwd
+ then
+ #user exist, add to group
+ echo "adding user ${option_user} to group admin"
+ usermod -a -G admin -g admin ${option_user}
+ else
+ #create user if it does not exist
+ [ -z "$FORCE" ] && read -p "user '${option_user}' does not exist, create (Y/n)" kk
+ if ! [ -z "$kk" -o "$kk"="y" -o "$kk"="Y" ]
+ then
+ exit
+ fi
+ echo "creating and configuring user ${option_user}"
+ useradd -m -G admin -g admin ${option_user}
+ #Password
+ if [ -z "$FORCE" ]
+ then
+ echo "Provide a password for ${option_user}"
+ passwd ${option_user}
+ else
+ echo -e "$option_user\n$option_user" | passwd --stdin ${option_user}
+ fi
+ fi
+
+}
+
+
+
+
+#1.2 input parameters
+FORCE=""
+while getopts "h" o; do
+ case "${o}" in
+ h)
+ _usage
+ exit -1
+ ;;
+ esac
+done
+shift $((OPTIND-1))
+
+
+
+if [ $# -lt 1 ]
+then
+ usage
+ exit
+fi
+
+[ -z "$1" ] && echo -e "ERROR: User argument is mandatory, --user=<user>\n" && _usage
+
+option_user=$1
+
+#check root privileges
+[ "${USER}" != "root" ] && echo "Needed root privileges" >&2 && exit 2
+
+
+echo '
+#################################################################
+##### INSTALL USER #####
+#################################################################'
+
+_install_user
+_add_user_to_visudo
+
+echo '
+#################################################################
+##### INSTALL NEEDED PACKETS #####
+#################################################################'
+_install_packages_dependencies
+
+_create_ovs_controller_config_path
+
+echo
+echo "Do not forget to copy the public ssh key into /home/${option_user}/.ssh/authorized_keys for authomatic login from openvim controller"
+echo
+
+echo "Reboot the system to make the changes effective"
# default : attached to the default host interface
# null : for data or ptp types. (To be changed in future versions)
shared: true # true, false: if shared it will consider by OPENVIM an EXTERNAL network available at OPENMANO
+ enable_dhcp : true # true, false to activate network dhcp over copmutes OVS mesh
+ cidr: 10.0.0.0/24 # Network CIDR from which to include or exclude addresses used for DHCP service lease offerings.
--- /dev/null
+##
+# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
+# This file is part of openvim
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+network:
+ name: mgmt
+ type: bridge_man
+ shared: true
+ enable_dhcp: true
+ cidr: 192.168.10.0/24
+
import auxiliary_functions as af
import json
import logging
+from netaddr import IPNetwork, IPSet, IPRange, all_matching_cidrs
HTTP_Bad_Request = 400
HTTP_Unauthorized = 401
#insert resources
nb_bridge_ifaces = nb_cores = nb_ifaces = nb_numas = 0
#insert bridged_ifaces
+
for iface in bridgedifaces:
#generate and insert a iface uuid
+ if 'enable_dhcp' in iface and iface['enable_dhcp']:
+ dhcp_first_ip = iface["dhcp_first_ip"]
+ del iface["dhcp_first_ip"]
+ dhcp_last_ip = iface["dhcp_last_ip"]
+ del iface["dhcp_last_ip"]
+ dhcp_cidr = iface["cidr"]
+ del iface["cidr"]
+ del iface["enable_dhcp"]
+ used_dhcp_ips = self._get_dhcp_ip_used_list(iface["net_id"])
+ iface["ip_address"] = self.get_free_ip_from_range(dhcp_first_ip, dhcp_last_ip,
+ dhcp_cidr, used_dhcp_ips)
+
iface['uuid'] = str(myUuid.uuid1()) # create_uuid
cmd = "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'ports')" % (iface['uuid'], uuid)
self.logger.debug(cmd)
r,c = self.format_error(e, "new_instance", cmd)
if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+ def get_free_ip_from_range(self, first_ip, last_ip, cidr, ip_used_list):
+ """
+ Calculate a free IP from a range given
+ :param first_ip: First dhcp ip range
+ :param last_ip: Last dhcp ip range
+ :param cidr: net cidr
+ :param ip_used_list: contain all used ips to avoid ip collisions
+ :return:
+ """
+
+ ip_tools = IPNetwork(cidr)
+ cidr_len = ip_tools.prefixlen
+ ips = IPNetwork(first_ip + '/' + str(cidr_len))
+ ip_used_list.append(str(ips[0])) # first ip
+ ip_used_list.append(str(ips[1])) # gw ip
+ ip_used_list.append(str(ips[-1])) # broadcast ip
+ for vm_ip in ips:
+ if str(vm_ip) not in ip_used_list:
+ return vm_ip
+
+ return None
+
+ def _get_dhcp_ip_used_list(self, net_id):
+ """
+ REtreive from DB all ips already used by the dhcp server for a given net
+ :param net_id:
+ :return:
+ """
+ WHERE={'type': 'instance:ovs', 'net_id': net_id}
+ for retry_ in range(0, 2):
+ cmd = ""
+ self.cur = self.con.cursor(mdb.cursors.DictCursor)
+ select_ = "SELECT uuid, ip_address FROM ports "
+
+ if WHERE is None or len(WHERE) == 0:
+ where_ = ""
+ else:
+ where_ = "WHERE " + " AND ".join(
+ map(lambda x: str(x) + (" is Null" if WHERE[x] is None else "='" + str(WHERE[x]) + "'"),
+ WHERE.keys()))
+ limit_ = "LIMIT 100"
+ cmd = " ".join((select_, where_, limit_))
+ self.logger.debug(cmd)
+ self.cur.execute(cmd)
+ ports = self.cur.fetchall()
+ ip_address_list = []
+ for port in ports:
+ ip_address_list.append(port['ip_address'])
+
+ return ip_address_list
+
+
def delete_instance(self, instance_id, tenant_id, net_dataplane_list, ports_to_free, net_ovs_list, logcause="requested by http"):
for retry_ in range(0,2):
cmd=""
net_dataplane_list.append(net[0])
# get ovs manangement nets
- cmd = "SELECT DISTINCT net_id, vlan FROM ports WHERE instance_id='{}' AND net_id is not Null AND "\
+ cmd = "SELECT DISTINCT net_id, vlan, ip_address, mac FROM ports WHERE instance_id='{}' AND net_id is not Null AND "\
"type='instance:ovs'".format(instance_id)
self.logger.debug(cmd)
self.cur.execute(cmd)
"log_level_db": log_level_schema,
"log_level_of": log_level_schema,
"network_type": {"type": "string", "enum": ["ovs", "bridge"]},
+ "ovs_controller_file_path": path_schema,
+ "ovs_controller_user": nameshort_schema,
+
+ "ovs_controller_ip": nameshort_schema
},
"patternProperties": {
"of_*" : {"type": ["string", "integer", "boolean"]}
"provider:physical":net_bind_schema,
"cidr":cidr_schema,
"enable_dhcp": {"type":"boolean"},
- "dhcp_first_ip": ip_schema,
- "dhcp_last_ip": ip_schema,
+ # "dhcp_first_ip": ip_schema,
+ # "dhcp_last_ip": ip_schema,
"bind_net":name_schema, #can be name, or uuid
"bind_type":{"oneOf":[{"type":"null"},{"type":"string", "pattern":"^vlan:[0-9]{1,4}$"}]}
},