#!/usr/bin/env python from pyeole import process from pyeole.log import init_logging from creole.client import CreoleClient from tempfile import mkstemp import sys import os import csv import logging import re LOG_FILE = '/var/log/one/eole-one-node.log' logger = None class RunCmdError(Exception): pass class OneClient(): def __init__(self, user): self.user = None self.auth = None self.root = '/var/lib/one' if user: self.user = user else: self.user = 'oneadmin' user_info = process.system_out(['getent', 'passwd', user])[1] if user_info: self.root = user_info.split(':')[5] command = ['cat', u'{0}/.one/one_auth'.format(self.root)] res = process.system_out(command) if res[0] == 0: self.auth = res[1].split(':') else: msg = u"OneClient: unable to authenticate: '{stdout}', '{stderr}'" logger.error(msg.format(stdout=res[1], stderr=res[2])) def __run_cmd__(self, cmd): logger.debug(u"OneClient: execute command '{cmd}'".format(cmd=cmd)) command = list(cmd) command.extend(['--user', self.auth[0]]) command.extend(['--password', self.auth[1]]) res = process.system_out(command) if res[0] == 0: if 'list' in cmd: out_lines = [] if res: for line in res[1].split('\n'): if len(line) == 0: next elif re.match('^.*ID ', line): next else: out_lines.append(line.split()) return out_lines else: return res else: msg = u"OneClient: error executing '{cmd}': '{stdout}', '{stderr}'" logger.error(msg.format(cmd=cmd, stdout=res[1], stderr=res[2])) return False def get_hosts(self): """ get the list of hosts """ logger.debug(u"OneClient: list all hosts") cmd = ['onehost', 'list'] cmd.extend(['-l', 'ID,NAME']) res = self.__run_cmd__(cmd) return(res) def get_clusters(self): """ get the cluster list """ logger.debug(u"OneClient: list all clusters") cmd = ['onecluster', 'list'] cmd.extend(['-l', 'ID,NAME']) return self.__run_cmd__(cmd) def get_networks(self): """ get the virtual network list """ logger.debug(u"OneClient: list all networks") cmd = ['onevnet', 'list'] cmd.extend(['-l', 'ID,NAME']) return self.__run_cmd__(cmd) def get_cluster_id_by_name(self, name): logger.debug(u"OneClient: get cluster named '{name}'".format(name=name)) cmd = ['onecluster', 'list'] cmd.extend(['-f', 'NAME={0}'.format(name)]) res = self.__run_cmd__(cmd) ID = res[0][0] return ID def get_vnet_id_by_name(self, name): logger.debug(u"OneClient: get network named '{name}'".format(name=name)) cmd = ['onevnet', 'list'] cmd.extend(['-f', 'NAME={0}'.format(name)]) res = self.__run_cmd__(cmd) ID = res[0][0] return ID def create_network(self, templatefile, cluster, vnet_name): """ Create a network """ logger.info(u"OneClient: create network named '{name}'".format(name=vnet_name)) cmd = ['onevnet', 'create', templatefile] res = self.__run_cmd__(cmd) if res and res[0] == 0: msg = u"OneClient: attach vnet '{vnet}' to cluster '{cluster}'" logger.info(msg.format(vnet=vnet_name, cluster=cluster)) clt_id = self.get_cluster_id_by_name(cluster) vnet_id = self.get_vnet_id_by_name(vnet_name) res = self.__run_cmd__(['onecluster', 'addvnet', clt_id, vnet_id]) if not res: print("Error attaching {0} vnet to {1} cluster".format(vnet_name, cluster)) return False else: os.remove(templatefile) return True else: logger.error(u"Creation of virtual network with template {0} failed".format(templatefile)) return False def update_network(self, templatefile, cluster, vnet_name): """ Update a network """ logger.info(u"OneClient: update network named '{name}'".format(name=vnet_name)) vnet_id = self.get_vnet_id_by_name(vnet_name) cmd = ['onevnet', 'update'] cmd.extend(['--user', self.auth[0]]) cmd.extend(['--password', self.auth[1][:-1]]) cmd.extend([vnet_id, templatefile]) res = process.system_out(cmd) if res[0] == 0: os.remove(templatefile) return True else: logger.error(u"Update of virtual network with template {0} failed".format(templatefile)) return False def delete_network(self, vnet_id): logger.info(u"OneClient: delete network with ID '{id}'".format(id=vnet_id)) cmd = ['onevnet', 'delete'] cmd.extend(['--user', self.auth[0]]) cmd.extend(['--password', self.auth[1][:-1]]) cmd.append(vnet_id) res = process.system_out(cmd) if res[0] == 0: logger.info(u"Network {0} deleted".format(vnet_id)) return True else: logger.error(u"Error deleting network {0}".format(vnet_id)) return False class OneNetwork(): def create(self, one_client): logger.debug(u"OneNetwork: create network named '{name}'".format(name=self.zone)) tmpl_file = self.create_template() if one_client.create_network(tmpl_file, self.cluster, self.zone): logger.info(u"Virtual network {0} created".format(self.zone)) return True else: logger.error(u"Error Creating virtual network {0}".format(self.zone)) return False def update(self, one_client): logger.debug(u"OneNetwork: update network named '{name}'".format(name=self.zone)) tmpl_file = self.create_template(True) if one_client.update_network(tmpl_file, self.cluster, self.zone): logger.info(u"Virtual network {0} updated".format(self.zone)) return True else: logger.error(u"Error Updating virtual network {0}".format(self.zone)) return False def manage(self, one_client): logger.debug(u"OneNetwork: manage network named '{name}'".format(name=self.zone)) found = False vnet = one_client.get_networks() network_name = self.zone for net in vnet: if network_name in net: found = True break if not found: return self.create(one_client) else: return self.update(one_client) class OneNetworkL3(OneNetwork): def __init__(self, net_info, cluster): self.swname = net_info[0] self.zone = u'{0}{1}'.format(net_info[10], net_info[1]) self.vlan = net_info[2] self.vnet_addr = net_info[3] self.vnet_mask = net_info[4] self.vnet_gw = net_info[5] self.vnet_rg_start = net_info[6] self.vnet_rg_size = net_info[7] self.vnet_dns = net_info[8] self.vnet_trunk = net_info[9] self.cluster = cluster def create_template(self, update=False): logger.debug(u"OneNetworkL3: create template for network named '{name}'".format(name=self.zone)) fd, tmp_path = mkstemp(prefix='oneVnet-') template = open(tmp_path, 'w') template.write('NAME = "{0}"\n'.format(self.zone)) template.write('VN_MAD = ovswitch\n') if (update is False): if self.vnet_rg_start and self.vnet_rg_size: template.write('AR=[\n') template.write('TYPE = "IP4",\n') template.write('IP = "{0}",\n'.format(self.vnet_rg_start)) template.write('SIZE = "{0}"\n'.format(self.vnet_rg_size)) template.write(']\n') else: template.write('TYPE = FIXED\n') if self.vlan: template.write('VLAN = yes\n') template.write('VLAN_ID = {0}\n'.format(self.vlan)) if self.vnet_trunk: template.write('VLAN_TAGGED_ID = {0}\n'.format(self.vnet_trunk)) template.write('BRIDGE = {0}\n'.format(self.swname)) template.write('NETWORK_ADDRESS = {0}\n'.format(self.vnet_addr)) template.write('NETWORK_MASK = {0}\n'.format(self.vnet_mask)) template.write('GATEWAY = {0}\n'.format(self.vnet_gw)) template.write('DNS = {0}\n'.format(self.vnet_dns)) template.close() return tmp_path class OneNetworkL2(OneNetwork): def __init__(self, net_info, cluster): self.swname = net_info[0] self.zone = u'{0}{1}'.format(net_info[6], net_info[1]) self.net_size = net_info[2] self.first_mac = net_info[3] self.tag = net_info[4] self.trunk = net_info[5] self.cluster = cluster def create_template(self,update=False): logger.debug(u"OneNetworkL2: create template for network named '{name}'".format(name=self.zone)) fd, tmp_path = mkstemp(prefix='oneVnet-') template = open(tmp_path, 'w') template.write('NAME = "{0}"\n'.format(self.zone)) template.write('VN_MAD = ovswitch\n') if self.tag: template.write('VLAN = yes\n') template.write('VLAN_ID = "{0}"\n'.format(self.tag)) if self.trunk: template.write('VLAN_TAGGED_ID = "{0}""\n'.format(self.trunk)) template.write('BRIDGE = {0}\n'.format(self.swname)) if update is False and self.net_size: template.write("AR=[\n") template.write(' TYPE = "ETHER",\n') if self.first_mac: template.write(' MAC = "{0}",\n'.format(self.first_mac)) template.write(' SIZE = "{0}"\n'.format(self.net_size)) template.write("]\n") template.close() return tmp_path def main(): global logger logger = init_logging(name='postservice.opennebula.network', level=u'INFO', as_root=True, console=True, syslog=True) logger.debug(u"Configure OpenNebula networks") client = CreoleClient() mode_ha = client.get_creole('activer_one_ha') if mode_ha == "oui": indx = client.get_creole('one_ha_server_index') if indx != 0: # Mode HA is on and we are not in the Leader exit(0) one_client = OneClient('oneadmin') networks = [] cluster = client.get_creole('one_cluster_name') swname = client.get_creole('ovs_sw_name') zones = client.get_creole('vnets') vlans = client.get_creole('vnet_vlan_tag') vnet_addr = client.get_creole('vnet_network_addr') vnet_mask = client.get_creole('vnet_network_mask') vnet_dns = client.get_creole('vnet_network_dns') vnet_gw = client.get_creole('vnet_network_gw') vnet_rg_start = client.get_creole('vnet_range_start') vnet_rg_size = client.get_creole('vnet_range_size') vnet_trunk = client.get_creole('vnet_vlan_trunk') l2_vnet = client.get_creole('l2_vnets') l2_vnet_size = client.get_creole('l2_vnet_size') l2_vnet_vlan_tag = client.get_creole('l2_vnet_vlan_tag') l2_vnet_vlan_trunk = client.get_creole('l2_vnet_vlan_trunk') l2_vnet_first_mac = client.get_creole('l2_vnet_first_mac') net_prefix = "CR_" processed = [] for cpt in range(len(zones)): if zones[cpt] not in processed: info = [] info.append(swname) info.append(zones[cpt]) info.append(vlans[cpt]) info.append(vnet_addr[cpt]) info.append(vnet_mask[cpt]) info.append(vnet_gw[cpt]) info.append(vnet_rg_start[cpt]) info.append(vnet_rg_size[cpt]) info.append(vnet_dns[cpt]) info.append(vnet_trunk[cpt]) info.append(net_prefix) networks.append(OneNetworkL3(info, cluster)) processed.append(zones[cpt]) for i in range(len(l2_vnet)): if l2_vnet[i] not in processed: net_info = [] net_info.append(swname) net_info.append(l2_vnet[i]) net_info.append(l2_vnet_size[i]) net_info.append(l2_vnet_first_mac[i]) net_info.append(l2_vnet_vlan_tag[i]) net_info.append(l2_vnet_vlan_trunk[i]) net_info.append(net_prefix) networks.append(OneNetworkL2(net_info, cluster)) processed.append(l2_vnet[i]) if client.get_creole('activer_openvswitch'): for network in networks: if not network.manage(one_client): exit(1) else: logger.info(u'Open vSwitch disabled no need to configure virtual networks') networks = one_client.get_networks() for net in networks: name = net[1] if name.startswith(net_prefix): if not name[3:] in zones and not name[3:] in l2_vnet: one_client.delete_network(net[0]) exit(0) main()