Exemplo n.º 1
0
def parse_rows(rows, select_project=None):
    """Parse quota update data from the spreadsheet into a dictionary
    
    Expects 'rows' to include all rows, with row 0 being the header row
    Returns a dictionary of projects/quotas.
    """
    # NOTE: entry[17] is a required field in the Google Form, so it is safe
    # to assume entry[0:16] exists.
    
    # Column index in the Google Sheet for project name
    # This may need to be updated if question order on the form is changed
    PROJECT_COLUMN = 8
    
    project_list = []

    if select_project:
        try:
            rows = select_rows(select_project, PROJECT_COLUMN, rows)
            if len(rows) > 2:
                print ("WARNING: Multiple requests found for project {}. All "
                       "{} requests will be processed. You may need to close "
                       "multiple tickets.").format(args.project, len(rows) - 1)
        except ValueError as ve:
            raise argparse.ArgumentError(None, ve.message)
    else:
        rows = enumerate(rows)

    for idx, entry in rows:
        # ignore row 0 (the header row) and blank rows
        if (idx == 0) or (entry == []):
            continue
        # skip rows that have not been through approval/notification
        elif (entry[0].lower().strip() != 'approved') or (entry[1] == ''):
            # entry[0] is Approved
            # entry[1] is Helpdesk Notified
            continue
        else:
            project = dict()
            # entry [2] is Reminder Sent
            # entry [3] is Timestamp
            project['email'] = entry[4].replace(u'\xa0', ' ').strip()
            project['user_fullname'] = entry[5] + ' ' + entry[6]
            # entry[7] is organization
            project['name'] = entry[8]
            # entry[9] is Type of Increase
            # entry[10] is End Date
            quotas = {'instances': entry[11],
                      'cores': entry[12],
                      'ram': entry[13],
                      'floatingip': entry[14],
                      'network': entry[15],
                      'port': entry[16],
                      'volumes': entry[17],
                      'snapshots': entry[18],
                      'gigabytes': entry[19]}
            
            unchanged_quotas = [q for q in quotas if quotas[q] == '']
            for quota_name in unchanged_quotas:
                    del quotas[quota_name]

            for quota_name, value in quotas.iteritems():
                quotas[quota_name] = int(value)

            # OpenStack wants the RAM quota in MB, but the form requests it in
            # GB so the users aren't confused by multiplying by 1000 vs. 1024
            if 'ram' in quotas:
                quotas['ram'] = quotas['ram'] * 1024

            project['quotas'] = quotas

            # entry[20] is Comments - required field
            # entry[21] is MOC Notes - not required
            
            project['row'] = idx

            project_list.append(project)

    if not project_list:
        raise NoApprovedRequests(row_filter=select_project)

    return project_list
Exemplo n.º 2
0
def parse_rows(rows, select_user=None):
    """Parse spreadsheet user/project data into User and Project classes
    
    Expects 'rows' to include all rows, with row 0 being the header row
    Returns a dictionary of projects keyed by project name, and a list
    of rows that were not blank but failed to parse correctly.

    Select_user allows caller to handle requests from one user only.
    """
    # Column index in the Google Sheet for username
    # This may need to be updated if question order on the form is changed
    USER_COLUMN = 3

    projects = {}
    bad_rows = []

    if select_user:
        try:
            rows = select_rows(select_user, USER_COLUMN, rows)
            if len(rows) > 2:
                print(
                    "WARNING: Multiple requests found for user {}. All {} "
                    "requests will be processed.  You may need to close "
                    "multiple tickets.").format(args.user,
                                                len(rows) - 1)
        except ValueError as ve:
            raise argparse.ArgumentError(None, ve.message)
    else:
        rows = enumerate(rows)

    for idx, entry in rows:
        # ignore row 0 (the header row) and blank rows
        if (idx == 0) or (entry == []):
            continue
        elif (entry[0].lower().strip() != 'approved') or (entry[1] == ''):
            # Don't process requests that haven't gone through the
            # approval/notification process yet
            # entry[0] is Approved, entry[1] is Helpdesk Notified
            bad_rows.append((idx, ("Approval/Notification "
                                   "Incomplete: {}").format(entry[3])))
            continue
        try:
            # entry[2] is Timestamp
            email = entry[3].replace(u'\xa0', ' ').strip()
            user_info = {
                'user_name': email,
                'email': email,
                'first_name': entry[4],
                'last_name': entry[5]
            }

            if entry[6] == 'No':
                user_info.update({
                    'is_new': True,
                    'org': entry[7],
                    'role': entry[8],
                    'phone': entry[9],
                    'sponsor': entry[10],
                    'pin': entry[11],
                    'comment': entry[12]
                })
                # entry[13] asks whether a new or existing
                # project = only used for form navigation
                # FIXME: add option to choose "no project"
                # for teams who sign up for a new project
                # together?

            user = User(row=idx, **user_info)

            if entry[14] == "":
                # the user chose to join an existing project
                # info in entry[17] to entry[19]
                project_name = entry[17]
                if project_name not in projects:
                    project = Project(row=idx,
                                      name=project_name,
                                      contact_name=entry[18],
                                      contact_email=entry[19])
                    projects[project.name] = project

                projects[project_name].users.append(user)

            elif entry[14] in projects:
                # FIXME:
                # This should probably raise an error of some sort.  It
                # covers 2 weird edge cases, either:
                #   a) the project exists, another user from this batch
                #      asked to be added to it
                #   b) project doesn't exist, but another user from this
                #      batch requested a new project with this name.
                # For now, while we get stuff working, just assume they are
                # the same project.
                projects[entry[14]].users.append(user)

            else:
                # a new project was requested - info in entry[14] to entry[16]
                project = Project(row=idx,
                                  name=entry[14],
                                  contact_name=user.first_name + " " +
                                  user.last_name,
                                  contact_email=user.email,
                                  description=entry[15],
                                  is_new=True)
                project.users.append(user)

                try:
                    for add_user in entry[16].split(','):
                        add_user = add_user.strip()
                        existing_user = User(row=idx,
                                             user_name=add_user,
                                             email=add_user,
                                             is_requestor=False)
                        project.users.append(existing_user)
                except IndexError:
                    # entry[16] is the last possible filled cell in a new
                    # project entry, so if it was left blank it's not there
                    # FIXME by changing field order on the forms?
                    pass
                except:
                    # If the user typed something in this box but didn't follow
                    # instructions
                    print(
                        "WARNING: unable to add users for project {} from "
                        "input: {}.\nIf this is a valid request, add these "
                        "users manually.").format(entry[14], entry[16])

                projects[project.name] = project
        except IndexError:
            # Somehow a required field is blank
            bad_rows.append((idx, "Missing Required Field"))

    return projects, bad_rows