Skip to content

Commit

Permalink
Merge branch 'devel'
Browse files Browse the repository at this point in the history
  • Loading branch information
micafer committed Jun 17, 2015
2 parents f211f56 + 56c7ac9 commit b54ca74
Show file tree
Hide file tree
Showing 27 changed files with 1,229 additions and 3,868 deletions.
184 changes: 100 additions & 84 deletions IM/ConfManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,10 @@ def check_vm_ips(self, timeout = Config.WAIT_RUNNING_VM_TIMEOUT):
# If the IP is not Available try to update the info
vm.update_status(self.auth)

# If the VM is not in a "running" state, return false
if vm.state in [VirtualMachine.OFF, VirtualMachine.FAILED, VirtualMachine.STOPPED]:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": Error waiting all the VMs to have a correct IP. VM ID: " + str(vm.id) + " is not running.")
self.inf.set_configured(False)
return False
# If the VM is not in a "running" state, ignore it
if vm.state in VirtualMachine.NOT_RUNNING_STATES:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": The VM ID: " + str(vm.id) + " is not running, do not wait it to have an IP.")
continue

if vm.hasPublicNet():
ip = vm.getPublicIP()
Expand Down Expand Up @@ -225,55 +224,52 @@ def run(self):

last_step = step

def launch_ctxt_agent(self, vm, tasks, max_retries = 3):
def launch_ctxt_agent(self, vm, tasks):
"""
Launch the ctxt agent to configure the specified tasks in the specified VM
"""
pid = None
retries = 0
while not pid and retries < max_retries:
retries += 1
try:
ip = vm.getPublicIP()
if not ip:
ip = vm.getPrivateIP()
remote_dir = Config.REMOTE_CONF_DIR + "/" + ip + "_" + str(vm.getSSHPort())
tmp_dir = tempfile.mkdtemp()

ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Create the configuration file for the contextualization agent")
conf_file = tmp_dir + "/config.cfg"
self.create_vm_conf_file(conf_file, vm.im_id, tasks, remote_dir)

ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Copy the contextualization agent config file")

# Copy the contextualization agent config file
ssh = self.inf.vm_master.get_ssh()
ssh.sftp_mkdir(remote_dir)
ssh.sftp_put(conf_file, remote_dir + "/" + os.path.basename(conf_file))

shutil.rmtree(tmp_dir, ignore_errors=True)

(pid, _, _) = ssh.execute("nohup python_ansible " + Config.REMOTE_CONF_DIR + "/ctxt_agent.py "
+ Config.REMOTE_CONF_DIR + "/general_info.cfg "
+ remote_dir + "/" + os.path.basename(conf_file)
+ " > " + remote_dir + "/stdout" + " 2> " + remote_dir + "/stderr < /dev/null & echo -n $!")

ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Ansible process to configure " + str(vm.im_id) + " launched with pid: " + pid)

vm.ctxt_pid = pid
vm.launch_check_ctxt_process()
except:
pid = None
ConfManager.logger.exception("Inf ID: " + str(self.inf.id) + ": Error (%d/%d) launching the ansible process to configure %s" % (retries, max_retries, str(vm.im_id)))
time.sleep(retries*2)

# If the process is not correctly launched the configuration of this VM fails
if pid is None:
vm.ctxt_pid = None
vm.configured = False
vm.cont_out = "Error launching the contextualization agent to configure the VM. Check the SSH connection."
try:
ip = vm.getPublicIP()
if not ip:
ip = vm.getPrivateIP()
remote_dir = Config.REMOTE_CONF_DIR + "/" + ip + "_" + str(vm.getSSHPort())
tmp_dir = tempfile.mkdtemp()

ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Create the configuration file for the contextualization agent")
conf_file = tmp_dir + "/config.cfg"
self.create_vm_conf_file(conf_file, vm.im_id, tasks, remote_dir)

ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Copy the contextualization agent config file")

# Copy the contextualization agent config file
ssh = self.inf.vm_master.get_ssh(retry = True)
ssh.sftp_mkdir(remote_dir)
ssh.sftp_put(conf_file, remote_dir + "/" + os.path.basename(conf_file))

shutil.rmtree(tmp_dir, ignore_errors=True)

(pid, _, _) = ssh.execute("nohup python_ansible " + Config.REMOTE_CONF_DIR + "/ctxt_agent.py "
+ Config.REMOTE_CONF_DIR + "/general_info.cfg "
+ remote_dir + "/" + os.path.basename(conf_file)
+ " > " + remote_dir + "/stdout" + " 2> " + remote_dir + "/stderr < /dev/null & echo -n $!")

ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Ansible process to configure " + str(vm.im_id) + " launched with pid: " + pid)

vm.ctxt_pid = pid
vm.launch_check_ctxt_process()
except:
pid = None
ConfManager.logger.exception("Inf ID: " + str(self.inf.id) + ": Error launching the ansible process to configure %s" % str(vm.im_id))

return pid
# If the process is not correctly launched the configuration of this VM fails
if pid is None:
vm.ctxt_pid = None
vm.configured = False
vm.cont_out = "Error launching the contextualization agent to configure the VM. Check the SSH connection."

return pid

def generate_inventory(self, tmp_dir):
"""
Expand Down Expand Up @@ -306,6 +302,19 @@ def generate_inventory(self, tmp_dir):

for vm in vm_group[group]:
if not vm.destroy:
# first try to use the public IP
ip = vm.getPublicIP()
if not ip:
ip = vm.getPrivateIP()

if not ip:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": The VM ID: " + str(vm.id) + " does not have an IP. It will not be included in the inventory file.")
continue

if vm.state in VirtualMachine.NOT_RUNNING_STATES:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": The VM ID: " + str(vm.id) + " is not running. It will not be included in the inventory file.")
continue

ifaces_im_vars = ''
for i in range(vm.getNumNetworkIfaces()):
iface_ip = vm.getIfaceIP(i)
Expand All @@ -317,10 +326,7 @@ def generate_inventory(self, tmp_dir):
ifaces_im_vars += ' IM_NODE_NET_' + str(i) + '_DOMAIN=' + nodedom
ifaces_im_vars += ' IM_NODE_NET_' + str(i) + '_FQDN=' + nodename + "." + nodedom

# first try to use the public IP
ip = vm.getPublicIP()
if not ip:
ip = vm.getPrivateIP()


# the master node
# TODO: Known issue: the master VM must set the public network in the iface 0
Expand Down Expand Up @@ -379,18 +385,22 @@ def generate_etc_hosts(self, tmp_dir):
vm = vm_group[group][0]

for vm in vm_group[group]:
# first try to use the public IP
ip = vm.getPublicIP()
if not ip:
ip = vm.getPrivateIP()

if not ip:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": The VM ID: " + str(vm.id) + " does not have an IP. It will not be included in the /etc/hosts file.")
continue

for i in range(vm.getNumNetworkIfaces()):
if vm.getRequestedNameIface(i):
if vm.getIfaceIP(i):
(nodename, nodedom) = vm.getRequestedNameIface(i, default_domain = Config.DEFAULT_DOMAIN)
hosts_out.write(vm.getIfaceIP(i) + " " + nodename + "." + nodedom + " " + nodename + "\r\n")
else:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": Net interface " + str(i) + " request a name, but it does not have an IP.")

# first try to use the public IP
ip = vm.getPublicIP()
if not ip:
ip = vm.getPrivateIP()

# the master node
# TODO: Known issue: the master VM must set the public network in the iface 0
Expand Down Expand Up @@ -505,17 +515,14 @@ def configure_master(self):
try:
ConfManager.logger.info("Inf ID: " + str(self.inf.id) + ": Start the contextualization process.")

ssh = self.inf.vm_master.get_ssh()
ssh = self.inf.vm_master.get_ssh(retry=True)
# Activate tty mode to avoid some problems with sudo in REL
ssh.tty = True

# Get the groups for the different VM types
vm_group = self.inf.get_vm_list_by_system_name()

# configuration dir os th emaster node to copy all the contextualization files
tmp_dir = tempfile.mkdtemp()
# Now call the ansible installation process on the master node
configured_ok = self.configure_ansible(vm_group, ssh, tmp_dir)
configured_ok = self.configure_ansible(ssh, tmp_dir)

if not configured_ok:
ConfManager.logger.error("Inf ID: " + str(self.inf.id) + ": Error in the ansible installation process")
Expand Down Expand Up @@ -605,7 +612,7 @@ def wait_master(self):
ConfManager.logger.info("Inf ID: " + str(self.inf.id) + ": VMs available.")

# Check and change if necessary the credentials of the master vm
ssh = self.inf.vm_master.get_ssh()
ssh = self.inf.vm_master.get_ssh(retry=True)
# Activate tty mode to avoid some problems with sudo in REL
ssh.tty = True
self.change_master_credentials(ssh)
Expand Down Expand Up @@ -678,7 +685,7 @@ def generate_playbooks_and_hosts(self):
# TODO: Study why it is needed
time.sleep(2)

ssh = self.inf.vm_master.get_ssh()
ssh = self.inf.vm_master.get_ssh(retry=True)
self.inf.add_cont_msg("Copying YAML, hosts and inventory files.")
ConfManager.logger.debug("Inf ID: " + str(self.inf.id) + ": Copying YAML files.")
ssh.sftp_mkdir(remote_dir)
Expand Down Expand Up @@ -951,7 +958,7 @@ def create_all_recipe(self, tmp_dir, filename):
conf_all_out.close()
return all_filename

def configure_ansible(self, vm_group, ssh, tmp_dir):
def configure_ansible(self, ssh, tmp_dir):
"""
Install ansible in the master node
Expand All @@ -960,6 +967,8 @@ def configure_ansible(self, vm_group, ssh, tmp_dir):
- tmp_dir(str): Temp directory where all the playbook files will be stored.
Returns: True if the process finished sucessfully, False otherwise.
"""
# Get the groups for the different VM types
vm_group = self.inf.get_vm_list_by_system_name()

# Create the ansible inventory file
with open(tmp_dir + "/inventory.cfg", 'w') as inv_out:
Expand Down Expand Up @@ -1031,26 +1040,33 @@ def create_general_conf_file(self, conf_file, vm_list):
conf_data['playbook_retries'] = Config.PLAYBOOK_RETRIES
conf_data['vms'] = []
for vm in vm_list:
vm_conf_data = {}
vm_conf_data['id'] = vm.im_id
if vm.im_id == self.inf.vm_master.im_id:
vm_conf_data['master'] = True
if vm.state in VirtualMachine.NOT_RUNNING_STATES:
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": The VM ID: " + str(vm.id) + " is not running, do not include in the general conf file.")
else:
vm_conf_data['master'] = False
# first try to use the public IP
vm_conf_data['ip'] = vm.getPublicIP()
if not vm_conf_data['ip']:
vm_conf_data['ip'] = vm.getPrivateIP()
vm_conf_data['ssh_port'] = vm.getSSHPort()
creds = vm.getCredentialValues()
new_creds = vm.getCredentialValues(new=True)
(vm_conf_data['user'], vm_conf_data['passwd'], _, vm_conf_data['private_key']) = creds
# If there are new creds to set to the VM
if len(list(set(new_creds))) > 1 or list(set(new_creds))[0] != None:
if cmp(new_creds,creds) != 0:
(_, vm_conf_data['new_passwd'], vm_conf_data['new_public_key'], vm_conf_data['new_private_key']) = new_creds

conf_data['vms'].append(vm_conf_data)
vm_conf_data = {}
vm_conf_data['id'] = vm.im_id
if vm.im_id == self.inf.vm_master.im_id:
vm_conf_data['master'] = True
else:
vm_conf_data['master'] = False
# first try to use the public IP
vm_conf_data['ip'] = vm.getPublicIP()
if not vm_conf_data['ip']:
vm_conf_data['ip'] = vm.getPrivateIP()
vm_conf_data['ssh_port'] = vm.getSSHPort()
creds = vm.getCredentialValues()
new_creds = vm.getCredentialValues(new=True)
(vm_conf_data['user'], vm_conf_data['passwd'], _, vm_conf_data['private_key']) = creds
# If there are new creds to set to the VM
if len(list(set(new_creds))) > 1 or list(set(new_creds))[0] != None:
if cmp(new_creds,creds) != 0:
(_, vm_conf_data['new_passwd'], vm_conf_data['new_public_key'], vm_conf_data['new_private_key']) = new_creds

if not vm_conf_data['ip']:
# if the vm does not have an IP, do not iclude it to avoid errors configurin gother VMs
ConfManager.logger.warn("Inf ID: " + str(self.inf.id) + ": The VM ID: " + str(vm.id) + " does not have an IP, do not include in the general conf file.")
else:
conf_data['vms'].append(vm_conf_data)

conf_data['conf_dir'] = Config.REMOTE_CONF_DIR

Expand Down
7 changes: 6 additions & 1 deletion IM/InfrastructureInfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def add_cont_msg(self, msg):

def get_vm_list(self):
"""
Get the list of not destroyed VMs
Get the list of not destroyed VMs.
"""
with self._lock:
res = [vm for vm in self.vm_list if not vm.destroy]
Expand All @@ -176,6 +176,9 @@ def get_vm(self, str_vm_id):
raise IncorrectVMException()

def get_vm_list_by_system_name(self):
"""
Get the list of not destroyed VMs grouped by the name of system.
"""
groups = {}
for vm in self.get_vm_list():
if vm.getRequestedSystem().name in groups:
Expand Down Expand Up @@ -385,6 +388,8 @@ def Contextualize(self, auth):
ctxt_task.append((-1,0,self,['configure_master', 'generate_playbooks_and_hosts']))

for vm in self.get_vm_list():
# Assure to update the VM status before running the ctxt process
vm.update_status(auth)
vm.cont_out = ""
vm.configured = None
tasks = {}
Expand Down
Loading

0 comments on commit b54ca74

Please sign in to comment.