def get_admin_ips(cls, node): netmanager = NetworkManager() admin_net_id = netmanager.get_admin_network_id() admin_ips = set([ i.ip_addr for i in db().query(IPAddr). filter_by(node=node.id). filter_by(network=admin_net_id)]) return admin_ips
def get_controller_nodes_ips(self, cluster): """ Return admin network ips """ network_manager = NetworkManager() admin_net_id = network_manager.get_admin_network_id() ip_addrs = [] for node in self.controllers(cluster): ip_addr = db().query(IPAddr).filter_by(node=node.id, network=admin_net_id).first().ip_addr ip_addrs.append(ip_addr) return ip_addrs
def prepare_syslog_dir(cls, node, prefix=None): logger.debug("Preparing syslog directories for node: %s", node.fqdn) if not prefix: prefix = settings.SYSLOG_DIR logger.debug("prepare_syslog_dir prefix=%s", prefix) old = os.path.join(prefix, str(node.ip)) bak = os.path.join(prefix, "%s.bak" % str(node.fqdn)) new = os.path.join(prefix, str(node.fqdn)) netmanager = NetworkManager() admin_net_id = netmanager.get_admin_network_id() links = map( lambda i: os.path.join(prefix, i.ip_addr), db().query(IPAddr.ip_addr).filter_by(node=node.id).filter_by( network=admin_net_id).all()) logger.debug("prepare_syslog_dir old=%s", old) logger.debug("prepare_syslog_dir new=%s", new) logger.debug("prepare_syslog_dir bak=%s", bak) logger.debug("prepare_syslog_dir links=%s", str(links)) # backup directory if it exists if os.path.isdir(new): logger.debug("New %s already exists. Trying to backup", new) if os.path.islink(bak): logger.debug( "Bak %s already exists and it is link. " "Trying to unlink", bak) os.unlink(bak) elif os.path.isdir(bak): logger.debug( "Bak %s already exists and it is directory. " "Trying to remove", bak) shutil.rmtree(bak) os.rename(new, bak) # rename bootstrap directory into fqdn if os.path.islink(old): logger.debug("Old %s exists and it is link. " "Trying to unlink", old) os.unlink(old) if os.path.isdir(old): logger.debug( "Old %s exists and it is directory. " "Trying to rename into %s", old, new) os.rename(old, new) else: logger.debug("Creating %s", new) os.makedirs(new) # creating symlinks for l in links: if os.path.islink(l) or os.path.isfile(l): logger.debug("%s already exists. " "Trying to unlink", l) os.unlink(l) if os.path.isdir(l): logger.debug( "%s already exists and it directory. " "Trying to remove", l) shutil.rmtree(l) logger.debug("Creating symlink %s -> %s", l, new) os.symlink(str(node.fqdn), l) os.system("/usr/bin/pkill -HUP rsyslog")
def prepare_syslog_dir(cls, node, prefix=None): logger.debug("Preparing syslog directories for node: %s", node.fqdn) if not prefix: prefix = settings.SYSLOG_DIR logger.debug("prepare_syslog_dir prefix=%s", prefix) old = os.path.join(prefix, str(node.ip)) bak = os.path.join(prefix, "%s.bak" % str(node.fqdn)) new = os.path.join(prefix, str(node.fqdn)) netmanager = NetworkManager() admin_net_id = netmanager.get_admin_network_id() links = map( lambda i: os.path.join(prefix, i.ip_addr), db().query(IPAddr.ip_addr). filter_by(node=node.id). filter_by(network=admin_net_id).all() ) logger.debug("prepare_syslog_dir old=%s", old) logger.debug("prepare_syslog_dir new=%s", new) logger.debug("prepare_syslog_dir bak=%s", bak) logger.debug("prepare_syslog_dir links=%s", str(links)) # backup directory if it exists if os.path.isdir(new): logger.debug("New %s already exists. Trying to backup", new) if os.path.islink(bak): logger.debug("Bak %s already exists and it is link. " "Trying to unlink", bak) os.unlink(bak) elif os.path.isdir(bak): logger.debug("Bak %s already exists and it is directory. " "Trying to remove", bak) shutil.rmtree(bak) os.rename(new, bak) # rename bootstrap directory into fqdn if os.path.islink(old): logger.debug("Old %s exists and it is link. " "Trying to unlink", old) os.unlink(old) if os.path.isdir(old): logger.debug("Old %s exists and it is directory. " "Trying to rename into %s", old, new) os.rename(old, new) else: logger.debug("Creating %s", new) os.makedirs(new) # creating symlinks for l in links: if os.path.islink(l) or os.path.isfile(l): logger.debug("%s already exists. " "Trying to unlink", l) os.unlink(l) if os.path.isdir(l): logger.debug("%s already exists and it directory. " "Trying to remove", l) shutil.rmtree(l) logger.debug("Creating symlink %s -> %s", l, new) os.symlink(str(node.fqdn), l) os.system("/usr/bin/pkill -HUP rsyslog")
def message(cls, task): logger.debug("ProvisionTask.message(task=%s)" % task.uuid) # this variable is used to set 'auth_key' in cobbler ks_meta cluster_attrs = task.cluster.attributes.merged_attrs_values() nodes = TaskHelper.nodes_to_provision(task.cluster) netmanager = NetworkManager() USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP # TODO: For now we send nodes data to orchestrator # which is cobbler oriented. But for future we # need to use more abstract data structure. nodes_data = [] for node in nodes: if not node.online: if not USE_FAKE: raise Exception( u"Node '%s' (id=%s) is offline." " Remove it from environment and try again." % (node.name, node.id) ) else: logger.warning( u"Node '%s' (id=%s) is offline." " Remove it from environment and try again." % (node.name, node.id) ) node_data = { 'profile': settings.COBBLER_PROFILE, 'power_type': 'ssh', 'power_user': '******', 'power_address': node.ip, 'name': TaskHelper.make_slave_name(node.id, node.role), 'hostname': node.fqdn, 'name_servers': '\"%s\"' % settings.DNS_SERVERS, 'name_servers_search': '\"%s\"' % settings.DNS_SEARCH, 'netboot_enabled': '1', 'ks_meta': { 'puppet_auto_setup': 1, 'puppet_master': settings.PUPPET_MASTER_HOST, 'puppet_version': settings.PUPPET_VERSION, 'puppet_enable': 0, 'mco_auto_setup': 1, 'install_log_2_syslog': 1, 'mco_pskey': settings.MCO_PSKEY, 'mco_vhost': settings.MCO_VHOST, 'mco_host': settings.MCO_HOST, 'mco_user': settings.MCO_USER, 'mco_password': settings.MCO_PASSWORD, 'mco_connector': settings.MCO_CONNECTOR, 'mco_enable': 1, 'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''), 'ks_spaces': "\"%s\"" % json.dumps( node.attributes.volumes).replace("\"", "\\\"") } } if node.status == "discover": logger.info( "Node %s seems booted with bootstrap image", node.id ) node_data['power_pass'] = settings.PATH_TO_BOOTSTRAP_SSH_KEY else: # If it's not in discover, we expect it to be booted # in target system. # TODO: Get rid of expectations! logger.info( "Node %s seems booted with real system", node.id ) node_data['power_pass'] = settings.PATH_TO_SSH_KEY # FIXME: move this code (updating) into receiver.provision_resp if not USE_FAKE: node.status = "provisioning" orm().add(node) orm().commit() # here we assign admin network IPs for node # one IP for every node interface netmanager.assign_admin_ips( node.id, len(node.meta.get('interfaces', [])) ) admin_net_id = netmanager.get_admin_network_id() admin_ips = set([i.ip_addr for i in orm().query(IPAddr). filter_by(node=node.id). filter_by(network=admin_net_id)]) for i in node.meta.get('interfaces', []): if 'interfaces' not in node_data: node_data['interfaces'] = {} node_data['interfaces'][i['name']] = { 'mac_address': i['mac'], 'static': '0', 'netmask': settings.ADMIN_NETWORK['netmask'], 'ip_address': admin_ips.pop(), } # interfaces_extra field in cobbler ks_meta # means some extra data for network interfaces # configuration. It is used by cobbler snippet. # For example, cobbler interface model does not # have 'peerdns' field, but we need this field # to be configured. So we use interfaces_extra # branch in order to set this unsupported field. if 'interfaces_extra' not in node_data: node_data['interfaces_extra'] = {} node_data['interfaces_extra'][i['name']] = { 'peerdns': 'no', 'onboot': 'no' } # We want node to be able to PXE boot via any of its # interfaces. That is why we add all discovered # interfaces into cobbler system. But we want # assignted fqdn to be resolved into one IP address # because we don't completely support multiinterface # configuration yet. if i['mac'] == node.mac: node_data['interfaces'][i['name']]['dns_name'] = node.fqdn node_data['interfaces_extra'][i['name']]['onboot'] = 'yes' nodes_data.append(node_data) if not USE_FAKE: TaskHelper.prepare_syslog_dir(node) message = { 'method': 'provision', 'respond_to': 'provision_resp', 'args': { 'task_uuid': task.uuid, 'engine': { 'url': settings.COBBLER_URL, 'username': settings.COBBLER_USER, 'password': settings.COBBLER_PASSWORD, }, 'nodes': nodes_data } } return message
def message(cls, task): logger.debug("ProvisionTask.message(task=%s)" % task.uuid) task_uuid = task.uuid cluster_id = task.cluster.id cluster_attrs = task.cluster.attributes.merged_attrs_values() netmanager = NetworkManager() nodes = orm().query(Node).filter_by( cluster_id=task.cluster.id, pending_deletion=False).order_by(Node.id) USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP nodes_to_provision = [] # FIXME: why can't we use needs_reprovision and pending_addition # attributes of node to constract valid list of nodes which need # to be provisioned and instead use this ugly loop? for node in nodes: if not node.online: if not USE_FAKE: raise Exception( u"Node '%s' (id=%s) is offline." " Remove it from environment and try again." % (node.name, node.id) ) else: logger.warning( u"Node '%s' (id=%s) is offline." " Remove it from environment and try again." % (node.name, node.id) ) if node.status in ('discover', 'provisioning') or \ (node.status == 'error' and node.error_type == 'provision'): nodes_to_provision.append(node) # TODO: For now we send nodes data to orchestrator # which are cobbler oriented. But for future we # need to use more abstract data structure. nodes_data = [] for node in nodes_to_provision: node_data = { 'profile': settings.COBBLER_PROFILE, 'power_type': 'ssh', 'power_user': '******', 'power_address': node.ip, 'name': TaskHelper.make_slave_name(node.id, node.role), 'hostname': node.fqdn, 'name_servers': '\"%s\"' % settings.DNS_SERVERS, 'name_servers_search': '\"%s\"' % settings.DNS_SEARCH, 'netboot_enabled': '1', 'ks_meta': { 'puppet_auto_setup': 1, 'puppet_master': settings.PUPPET_MASTER_HOST, 'puppet_version': settings.PUPPET_VERSION, 'puppet_enable': 0, 'mco_auto_setup': 1, 'install_log_2_syslog': 1, 'mco_pskey': settings.MCO_PSKEY, 'mco_vhost': settings.MCO_VHOST, 'mco_host': settings.MCO_HOST, 'mco_user': settings.MCO_USER, 'mco_password': settings.MCO_PASSWORD, 'mco_connector': settings.MCO_CONNECTOR, 'mco_enable': 1, 'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''), 'ks_spaces': "\"%s\"" % json.dumps( node.attributes.volumes).replace("\"", "\\\"") } } if node.status == "discover": logger.info( "Node %s seems booted with bootstrap image", node.id ) node_data['power_pass'] = settings.PATH_TO_BOOTSTRAP_SSH_KEY else: # If it's not in discover, we expect it to be booted # in target system. # TODO: Get rid of expectations! logger.info( "Node %s seems booted with real system", node.id ) node_data['power_pass'] = settings.PATH_TO_SSH_KEY # FIXME: move this code (updating) into receiver.provision_resp if not USE_FAKE: node.status = "provisioning" orm().add(node) orm().commit() # here we assign admin network IPs for node # one IP for every node interface netmanager.assign_admin_ips( node.id, len(node.meta.get('interfaces', [])) ) admin_net_id = netmanager.get_admin_network_id() admin_ips = set([i.ip_addr for i in orm().query(IPAddr). filter_by(node=node.id). filter_by(network=admin_net_id)]) for i in node.meta.get('interfaces', []): if 'interfaces' not in node_data: node_data['interfaces'] = {} node_data['interfaces'][i['name']] = { 'mac_address': i['mac'], 'static': '0', 'netmask': settings.ADMIN_NETWORK['netmask'], 'ip_address': admin_ips.pop(), } # interfaces_extra field in cobbler ks_meta # means some extra data for network interfaces # configuration. It is used by cobbler snippet. # For example, cobbler interface model does not # have 'peerdns' field, but we need this field # to be configured. So we use interfaces_extra # branch in order to set this unsupported field. if 'interfaces_extra' not in node_data: node_data['interfaces_extra'] = {} node_data['interfaces_extra'][i['name']] = { 'peerdns': 'no', 'onboot': 'no' } # We want node to be able to PXE boot via any of its # interfaces. That is why we add all discovered # interfaces into cobbler system. But we want # assignted fqdn to be resolved into one IP address # because we don't completely support multiinterface # configuration yet. if i['mac'] == node.mac: node_data['interfaces'][i['name']]['dns_name'] = node.fqdn node_data['interfaces_extra'][i['name']]['onboot'] = 'yes' nodes_data.append(node_data) if not USE_FAKE: TaskHelper.prepare_syslog_dir(node) message = { 'method': 'provision', 'respond_to': 'provision_resp', 'args': { 'task_uuid': task.uuid, 'engine': { 'url': settings.COBBLER_URL, 'username': settings.COBBLER_USER, 'password': settings.COBBLER_PASSWORD, }, 'nodes': nodes_data } } return message