def assign_to_pool(zone_number, cluster_id): vms = [] id_to_vm = {} selected_vm_ids = {} pools = None zone = None cluster = None memberships = {} try: Session() zone = Zone.query.get(zone_number) cluster = Cluster.query.filter_by(zone=zone, id=cluster_id).first() one_proxy = OneProxy(zone.xmlrpc_uri, zone.session_string, verify_certs=False) for membership in PoolMembership.query.join(VirtualMachinePool).filter_by(cluster=cluster).all(): memberships[membership.vm_id] = membership for vm in one_proxy.get_vms(): if vm.disk_cluster.id == cluster.id: vms.append(vm) id_to_vm[vm.id] = vm pools = VirtualMachinePool.get_all(cluster) except Exception as e: # raise e flash("Error fetching VMs in zone number {}: {}" .format(zone.number, e), category='danger') form = ActionForm() active_tab = 'create_new_pool' # Form submission handling begins if form.validate_on_submit(): # Determine which tab needs to be active based on the action if request.form['action'] is not None: print('something') active_tab = { 'create new pool': 'create_new_pool', 'add to pool': 'add_to_existing_pool'}[request.form['action']] # Get a list of clusters of all selected VMs--pools cannot span clusters selected_clusters = {} for id in request.form.getlist('chk_vm_id'): selected_vm_ids[int(id)] = id selected_clusters[id_to_vm[int(id)].disk_cluster.id] = True # Error checking begins proceed = True if len(selected_vm_ids) == 0: flash("No virtual machines were selected!", category='danger') proceed = False elif len(selected_clusters) != 1: flash("Selected VMs must all be in the same cluster", category='danger') proceed = False # Handle the appropriate action if able to proceed if proceed and request.form['action'] == 'add to pool': if (request.form['pool_id']) is None or request.form['pool_id'] == '': flash('No pool selected', category='danger') else: pool = VirtualMachinePool.query.get(request.form['pool_id']) for vm_id in selected_vm_ids.keys(): Session.add(PoolMembership(pool=pool, vm_name=id_to_vm[vm_id].name, vm_id=vm_id, date_added=datetime.utcnow())) Session.commit() flash(Markup('Successfully added {} members to pool <a href="{}">{}</a>'.format( len(selected_vm_ids), url_for('vpool_bp.view', pool_id=pool.id), pool.name, )), category='success') return redirect(url_for('vpool_bp.assign_to_pool', zone_number=zone.number, cluster_id=cluster.id)) if proceed and request.form['action'] == 'create new pool': try: if request.form['new_pool_name'] is None or request.form['new_pool_name'] == '': raise Exception('Pool name cannot be blank') pool = VirtualMachinePool( name=request.form['new_pool_name'], cluster=cluster, zone_number=zone.number, cardinality=len(selected_vm_ids)) Session.add(pool) Session.flush() for vm_id in selected_vm_ids.keys(): membership = PoolMembership(pool=pool, vm_name=id_to_vm[vm_id].name, vm_id=vm_id, date_added=datetime.utcnow()) memberships[vm_id] = membership Session.add(membership) Session.flush() Session.commit() flash(Markup('Successfully created <a href="{}">{}</a> with {} pool members'.format( url_for('vpool_bp.view', pool_id=pool.id), pool.name, len(selected_vm_ids))), category='success') except Exception as e: Session.rollback() flash('Error creating your new pool: {}'.format(e), category='danger') return render_template( 'vpool/assign_to_pool.html', form=form, zone=zone, cluster=cluster, vms=vms, memberships=memberships, selected_vm_ids=selected_vm_ids, pools=pools, active_tab_name=active_tab )
def plan_update(self, pool, update_members): task = crq = None try: pool = Session.merge(pool) start, end = jira.next_immediate_window_dates() logging = jira.instance.issue('SVC-1020') crq = jira.instance.create_issue( project=app.config['JIRA_CRQ_PROJECT'], issuetype={'name': 'Change Request'}, assignee={'name': app.config['JIRA_USERNAME']}, summary="[IMPLEMENT] {}".format(self.task.name), description=self.task.description, customfield_14530=start, customfield_14531=end, customfield_19031={'value': 'Maintenance'}, customfield_15152=[{ 'value': 'Global' }], customfield_19430={'value': 'No conflict with any restrictions'}, customfield_14135={ 'value': 'IPG', 'child': { 'value': 'IPG Big Data' } }, customfield_17679="Pool update required") self.log.msg("Created change request: {}".format(crq.key)) jira.instance.transition_issue( crq, app.config['JIRA_TRANSITION_CRQ_PLANNING']) self.log.msg("Transitioned {} to planning".format(crq.key)) jira.instance.create_issue_link('Relate', crq, logging) self.log.msg("Related {} to LOGGING service {}".format( crq.key, logging.key)) batch_size = floor( len(update_members) / app.config['BATCH_SIZE_PERCENT']) batch_size = 1 if batch_size == 0 else batch_size num_batches = min(len(update_members), app.config['BATCH_SIZE_PERCENT']) self.log.msg( "updating {} hosts in pool {} requires {} tasks with no more than {} hosts per task" .format(len(update_members), pool.name, num_batches, batch_size)) batch_num = 0 while len(update_members): batch_num += 1 task = jira.instance.create_issue( issuetype={'name': 'MOP Task'}, assignee={'name': app.config['JIRA_USERNAME']}, project=app.config['JIRA_CRQ_PROJECT'], summary='[TASK {}/{} (Update {}%)] {}'.format( batch_num, num_batches, app.config['BATCH_SIZE_PERCENT'], self.task.name), parent={'key': crq.key}, customfield_14135={ 'value': 'IPG', 'child': { 'value': 'IPG Big Data' } }, customfield_15150={'value': 'No'}) self.log.msg("Created task: {}".format(task.key)) jira.instance.transition_issue( task, app.config['JIRA_TRANSITION_TASK_PLANNING']) self.log.msg("Transitioned {} to planning".format(task.key)) env = Environment(loader=ObjectLoader()) for num in range(0, min(len(update_members), batch_size)): m = update_members.pop() filename = '{}.{}.template'.format(m.pool.id, m.vm_id) attachment_content = io.StringIO(m.current_template()) jira.instance.add_attachment(issue=task, filename=filename, attachment=attachment_content) self.log.msg("Attached template for {} to task {}".format( filename, task.key)) jira.instance.transition_issue( task, app.config['JIRA_TRANSITION_TASK_WRITTEN']) self.log.msg("Transitioned task {} to written".format(task.key)) jira.approver_instance.transition_issue( task, app.config['JIRA_TRANSITION_TASK_APPROVED']) self.log.msg("Approved task {}".format(task.key)) jira.instance.transition_issue( crq, app.config['JIRA_TRANSITION_CRQ_PLANNED_CHANGE']) self.log.msg("Transitioned change request {} to approved".format( task.key)) jira.approver_instance.transition_issue( crq, app.config['JIRA_TRANSITION_CRQ_APPROVED']) self.log.msg("Transitioned change request {} to approved".format( crq.key)) self.log.msg("Task ID {}".format(self.task.id)) db_ticket = PoolTicket(pool=pool, action_id=PoolTicketActions.update.value, ticket_key=crq.key, task=Session.merge(self.task)) Session.add(db_ticket) Session.commit() except Exception as e: Session.rollback() if crq is not None: jira.cancel_crq_and_tasks( crq, comment="failure creating change tickets") raise e
def plan_expansion(self, pool, expansion_names): task = crq = None try: pool = Session.merge(pool) start, end = jira.next_immediate_window_dates() logging = jira.instance.issue('SVC-1020') crq = jira.instance.create_issue( project=app.config['JIRA_CRQ_PROJECT'], issuetype={'name': 'Change Request'}, assignee={'name': app.config['JIRA_USERNAME']}, summary='[TEST IMPLEMENT] {}'.format(self.task.name), description=self.task.description, customfield_14530=start, customfield_14531=end, customfield_19031={'value': 'Maintenance'}, customfield_15152=[{ 'value': 'Global' }], customfield_19430={'value': 'No conflict with any restrictions'}, customfield_14135={ 'value': 'IPG', 'child': { 'value': 'IPG Big Data' } }, customfield_17679="Pool expansion required") self.log.msg("Created change request: {}".format(crq.key)) jira.instance.transition_issue( crq, app.config['JIRA_TRANSITION_CRQ_PLANNING']) self.log.msg("Transitioned {} to planning".format(crq.key)) jira.instance.create_issue_link('Relate', crq, logging) self.log.msg("Related {} to LOGGING service {}".format( crq.key, logging.key)) task = jira.instance.create_issue( issuetype={'name': 'MOP Task'}, assignee={'name': app.config['JIRA_USERNAME']}, project=app.config['JIRA_CRQ_PROJECT'], description= "Instanitate the attached templates in the zone associated " "to the pool identified in the filename <pool_id>.<hostname>", summary='[TEST IMPLEMENTATION TASK] {}'.format(self.task.name), parent={'key': crq.key}, customfield_14135={ 'value': 'IPG', 'child': { 'value': 'IPG Big Data' } }, customfield_15150={'value': 'No'}) self.log.msg("Created task: {}".format(task.key)) jira.instance.transition_issue( task, app.config['JIRA_TRANSITION_TASK_PLANNING']) self.log.msg("Transitioned {} to planning".format(task.key)) env = Environment(loader=ObjectLoader()) for hostname in expansion_names: vars = VarParser.parse_kv_strings_to_dict( pool.cluster.zone.vars, pool.cluster.vars, pool.vars, 'hostname={}'.format(hostname)) vm_template = env.from_string(pool.template).render(pool=pool, vars=vars) attachment_content = io.StringIO(vm_template) jira.instance.add_attachment(issue=task, filename='{}.{}.template'.format( pool.id, hostname), attachment=attachment_content) self.log.msg("Attached template for {} to task {}".format( hostname, task.key)) jira.instance.transition_issue( task, app.config['JIRA_TRANSITION_TASK_WRITTEN']) self.log.msg("Transitioned task {} to written".format(task.key)) jira.approver_instance.transition_issue( task, app.config['JIRA_TRANSITION_TASK_APPROVED']) self.log.msg("Approved task {}".format(task.key)) jira.instance.transition_issue( crq, app.config['JIRA_TRANSITION_CRQ_PLANNED_CHANGE']) self.log.msg("Transitioned task {} to approved".format(task.key)) jira.approver_instance.transition_issue( crq, app.config['JIRA_TRANSITION_CRQ_APPROVED']) self.log.msg("Transitioned change request {} to approved".format( crq.key)) self.log.msg("Task ID {}".format(self.task.id)) db_ticket = PoolTicket(pool=Session.merge(pool), action_id=PoolTicketActions.expand.value, ticket_key=crq.key, task=Session.merge(self.task)) Session.add(db_ticket) Session.commit() except Exception as e: Session.rollback() if crq is not None: jira.cancel_crq_and_tasks( crq, comment="failure creating change tickets") raise e
def assign_to_pool(zone_number, cluster_id): vms = [] id_to_vm = {} selected_vm_ids = {} pools = None zone = None cluster = None memberships = {} try: Session() zone = Zone.query.get(zone_number) cluster = Cluster.query.filter_by(zone=zone, id=cluster_id).first() one_proxy = OneProxy(zone.xmlrpc_uri, zone.session_string, verify_certs=False) for membership in PoolMembership.query.join( VirtualMachinePool).filter_by(cluster=cluster).all(): memberships[membership.vm_id] = membership for vm in one_proxy.get_vms(): if vm.disk_cluster.id == cluster.id: vms.append(vm) id_to_vm[vm.id] = vm pools = VirtualMachinePool.get_all(cluster) except Exception as e: # raise e flash("Error fetching VMs in zone number {}: {}".format( zone.number, e), category='danger') form = ActionForm() active_tab = 'create_new_pool' # Form submission handling begins if form.validate_on_submit(): # Determine which tab needs to be active based on the action if request.form['action'] is not None: print('something') active_tab = { 'create new pool': 'create_new_pool', 'add to pool': 'add_to_existing_pool' }[request.form['action']] # Get a list of clusters of all selected VMs--pools cannot span clusters selected_clusters = {} for id in request.form.getlist('chk_vm_id'): selected_vm_ids[int(id)] = id selected_clusters[id_to_vm[int(id)].disk_cluster.id] = True # Error checking begins proceed = True if len(selected_vm_ids) == 0: flash("No virtual machines were selected!", category='danger') proceed = False elif len(selected_clusters) != 1: flash("Selected VMs must all be in the same cluster", category='danger') proceed = False # Handle the appropriate action if able to proceed if proceed and request.form['action'] == 'add to pool': if (request.form['pool_id'] ) is None or request.form['pool_id'] == '': flash('No pool selected', category='danger') else: pool = VirtualMachinePool.query.get(request.form['pool_id']) for vm_id in selected_vm_ids.keys(): Session.add( PoolMembership(pool=pool, vm_name=id_to_vm[vm_id].name, vm_id=vm_id, date_added=datetime.utcnow())) Session.commit() flash(Markup( 'Successfully added {} members to pool <a href="{}">{}</a>' .format( len(selected_vm_ids), url_for('vpool_bp.view', pool_id=pool.id), pool.name, )), category='success') return redirect( url_for('vpool_bp.assign_to_pool', zone_number=zone.number, cluster_id=cluster.id)) if proceed and request.form['action'] == 'create new pool': try: if request.form['new_pool_name'] is None or request.form[ 'new_pool_name'] == '': raise Exception('Pool name cannot be blank') pool = VirtualMachinePool(name=request.form['new_pool_name'], cluster=cluster, zone_number=zone.number, cardinality=len(selected_vm_ids)) Session.add(pool) Session.flush() for vm_id in selected_vm_ids.keys(): membership = PoolMembership(pool=pool, vm_name=id_to_vm[vm_id].name, vm_id=vm_id, date_added=datetime.utcnow()) memberships[vm_id] = membership Session.add(membership) Session.flush() Session.commit() flash(Markup( 'Successfully created <a href="{}">{}</a> with {} pool members' .format(url_for('vpool_bp.view', pool_id=pool.id), pool.name, len(selected_vm_ids))), category='success') except Exception as e: Session.rollback() flash('Error creating your new pool: {}'.format(e), category='danger') return render_template('vpool/assign_to_pool.html', form=form, zone=zone, cluster=cluster, vms=vms, memberships=memberships, selected_vm_ids=selected_vm_ids, pools=pools, active_tab_name=active_tab)