Beispiel #1
0
def index(request):
    """Main page, where the magic happens."""
    filename = os.path.join(settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
    menus = yaml.load(filename)

    return render(request, 'chaperone/index.html', {
        'menus': menus,
        'application_full_name': settings.APP_FULLNAME,
    })
Beispiel #2
0
def vcenter_settings(request):
    """Main page, where the magic happens."""
    filename = os.path.join(settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
    menus = yaml.load(filename)

    try:
        vcenter_form = VCenterForm()
    except Exception, msg:
        LOG.warn("Exception ocured attempting to connect with vCenter: %s" % msg)
        vcenter_form = []
Beispiel #3
0
def index(request):
    """Main page, where the magic happens."""
    filename = os.path.join(settings.ANSWER_FILE_DIR,
                            settings.ANSWER_FILE_BASE)
    menus = yaml.load(filename)

    return render(request, 'chaperone/index.html', {
        'menus': menus,
        'application_full_name': settings.APP_FULLNAME,
    })
Beispiel #4
0
def vcenter_settings(request):
    """Main page, where the magic happens."""
    filename = os.path.join(settings.ANSWER_FILE_DIR,
                            settings.ANSWER_FILE_BASE)
    menus = yaml.load(filename)

    try:
        vcenter_form = VCenterForm()
    except Exception, msg:
        LOG.warn("Exception ocured attempting to connect with vCenter: %s" %
                 msg)
        vcenter_form = []
Beispiel #5
0
def write_answer_file(request, filename, new_answers=None):
    """Write out answer file, replacing old values with new ones, if given."""
    errors = []
    saved_answers = yaml.load(filename)
    if os.path.exists(filename):
        # Make a backup copy.
        backup_filename = '%s.bak' % filename
        yaml.dump(backup_filename, saved_answers)
        LOG.debug('Backup file %s written' % backup_filename)

    attributes_by_id = _get_attributes_by_id()
    if not new_answers:
        new_answers = request.REQUEST

    answers_data = {}
    for attr_id, attr in attributes_by_id.items():
        if new_answers and attr_id in new_answers:
            # Set new value.
            value = new_answers[attr_id]
            LOG.debug('Saving new value %s: %s' % (attr_id, value))

            # Check if there is a new file to save.
            if attr.get('input') == 'file' and value == '1':
                src = request.FILES.get('file-%s' % attr_id)
                dst_filename = os.path.join(settings.PREPARE_FILES_DIR,
                                            attr_id)
                if src:
                    with open(dst_filename, 'wb+') as dp:
                        for chunk in src.chunks():
                            dp.write(chunk)
                elif not os.path.exists(dst_filename):
                    # Should have a previously uploaded file available.
                    errors.append('File missing for %s.' % attr_id)
                    return errors
        else:
            # Use currently saved value.
            value = attr.get('value', '')
            LOG.debug('Saving old value %s: %s' % (attr_id, value))
        answers_data[attr_id] = str(value)

    LOG.debug('Dumping values: %s' % str(answers_data))
    yaml.dump(filename, answers_data)
    LOG.info('File %s written' % filename)
    return errors
Beispiel #6
0
def write_answer_file(request, filename, new_answers=None):
    """Write out answer file, replacing old values with new ones, if given."""
    errors = []
    saved_answers = yaml.load(filename)
    if os.path.exists(filename):
        # Make a backup copy.
        backup_filename = '%s.bak' % filename
        yaml.dump(backup_filename, saved_answers)
        LOG.debug('Backup file %s written' % backup_filename)

    attributes_by_id = _get_attributes_by_id()
    if not new_answers:
        new_answers = request.REQUEST

    answers_data = {}
    for attr_id, attr in attributes_by_id.items():
        if new_answers and attr_id in new_answers:
            # Set new value.
            value = new_answers[attr_id]
            LOG.debug('Saving new value %s: %s' % (attr_id, value))

            # Check if there is a new file to save.
            if attr.get('input') == 'file' and value == '1':
                src = request.FILES.get('file-%s' % attr_id)
                dst_filename = os.path.join(settings.PREPARE_FILES_DIR, attr_id)
                if src:
                    with open(dst_filename, 'wb+') as dp:
                        for chunk in src.chunks():
                            dp.write(chunk)
                elif not os.path.exists(dst_filename):
                    # Should have a previously uploaded file available.
                    errors.append('File missing for %s.' % attr_id)
                    return errors
        else:
            # Use currently saved value.
            value = attr.get('value', '')
            LOG.debug('Saving old value %s: %s' % (attr_id, value))
        answers_data[attr_id] = str(value)

    LOG.debug('Dumping values: %s' % str(answers_data))
    yaml.dump(filename, answers_data)
    LOG.info('File %s written' % filename)
    return errors
Beispiel #7
0
def _get_actions(menu_name, group_name):
    # Return action metadata for the given group. See
    # chaperone/local_settings.py.example for schema.
    filename = "%s/%s" % (settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
    menus = yaml.load(filename)

    # [{ ... }]
    for menu in menus:
        # { 'Menu': { ... } }
        for mname, groups in menu.items():
            if mname != menu_name or mname == settings.PREPARE_MENU:
                continue
            # [{ ... }]
            for group in groups:
                # { 'Group' : { ... } }
                for gname, actions in group.items():
                    if gname == group_name:
                        return actions
    return []
Beispiel #8
0
def _get_actions(menu_name, group_name):
    # Return action metadata for the given group. See
    # chaperone/local_settings.py.example for schema.
    filename = "%s/%s" % (settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
    menus = yaml.load(filename)

    # [{ ... }]
    for menu in menus:
        # { 'Menu': { ... } }
        for mname, groups in menu.items():
            if mname != menu_name or mname == settings.PREPARE_MENU:
                continue
            # [{ ... }]
            for group in groups:
                # { 'Group' : { ... } }
                for gname, actions in group.items():
                    if gname == group_name:
                        return actions
    return []
Beispiel #9
0
def _get_sections(container_name=None, group_name=None):
    # Return containers with all sections populated with the calculated
    # metadata for all attributes, or only the section for the given group in
    # the given container.
    #
    # See chaperone/local_settings.py.example for schema.
    base = os.path.join(settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
    menus = yaml.load(base)
    containers = []
    for menu in menus:
        for menu_name, menu_containers in menu.items():
            if menu_name == settings.PREPARE_MENU:
                containers = menu_containers
                break

    filename = os.path.join(settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_DEFAULT)
    saved_answers = yaml.load(filename)
    hidden_attributes = []
    shown_opt_attrs = []

    # Cache option values already retrieved in this request.
    opt_cache = yaml.load(settings.INPUT_OPTIONS)

    # [{ ... }]
    for container in containers:
        # { 'Container': { ... } }
        for cname, groups in container.items():
            if container_name and cname != container_name:
                continue
            # [{ ... }]
            for group in groups:
                # { 'Group': [...] }
                for gname, sections in group.items():
                    if group_name and gname != group_name:
                        continue
                    # [{ ... }]
                    for section in sections:
                        # { 'Section': [...] }
                        for attributes in section.values():
                            # [{ ... }]
                            for attr in attributes:
                                subsection = None
                                input_type = attr.get('input')
                                if input_type and input_type.lower() == 'multiform':
                                    new_hidden_attributes, new_shown_opt_attrs, new_attributes = _get_multiform(attr,saved_answers,opt_cache)
                                    attributes.extend(new_attributes)
                                else:
                                    new_hidden_attributes, new_shown_opt_attrs, new_attr = _get_form(attr,saved_answers,opt_cache)
                                    attr=new_attr
                                hidden_attributes.extend(new_hidden_attributes)
                                shown_opt_attrs.extend(new_shown_opt_attrs)

                    # Note which attributes not to display.
                    for section in sections:
                        for attributes in section.values():
                            for attr in attributes:
                                attr_id = attr['id']
                                if (attr_id in hidden_attributes and
                                        attr_id not in shown_opt_attrs):
                                    attr['hide'] = '1'
                    if group_name:
                        return sections

    return containers
Beispiel #10
0
def _get_sections(container_name=None, group_name=None):
    # Return containers with all sections populated with the calculated
    # metadata for all attributes, or only the section for the given group in
    # the given container.
    #
    # See chaperone/local_settings.py.example for schema.
    base = os.path.join(settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
    menus = yaml.load(base)
    containers = []
    for menu in menus:
        for menu_name, menu_containers in menu.items():
            if menu_name == settings.PREPARE_MENU:
                containers = menu_containers
                break

    filename = os.path.join(settings.ANSWER_FILE_DIR,
                            settings.ANSWER_FILE_DEFAULT)
    saved_answers = yaml.load(filename)
    hidden_attributes = []
    shown_opt_attrs = []

    # Cache option values already retrieved in this request.
    opt_cache = yaml.load(settings.INPUT_OPTIONS)

    # [{ ... }]
    for container in containers:
        # { 'Container': { ... } }
        for cname, groups in container.items():
            if container_name and cname != container_name:
                continue
            # [{ ... }]
            for group in groups:
                # { 'Group': [...] }
                for gname, sections in group.items():
                    if group_name and gname != group_name:
                        continue
                    # [{ ... }]
                    for section in sections:
                        # { 'Section': [...] }
                        for attributes in section.values():
                            # [{ ... }]
                            for attr in attributes:
                                subsection = None
                                input_type = attr.get('input')
                                if input_type and input_type.lower(
                                ) == 'multiform':
                                    new_hidden_attributes, new_shown_opt_attrs, new_attributes = _get_multiform(
                                        attr, saved_answers, opt_cache)
                                    attributes.extend(new_attributes)
                                else:
                                    new_hidden_attributes, new_shown_opt_attrs, new_attr = _get_form(
                                        attr, saved_answers, opt_cache)
                                    attr = new_attr
                                hidden_attributes.extend(new_hidden_attributes)
                                shown_opt_attrs.extend(new_shown_opt_attrs)

                    # Note which attributes not to display.
                    for section in sections:
                        for attributes in section.values():
                            for attr in attributes:
                                attr_id = attr['id']
                                if (attr_id in hidden_attributes
                                        and attr_id not in shown_opt_attrs):
                                    attr['hide'] = '1'
                    if group_name:
                        return sections

    return containers
Beispiel #11
0
def save_vcenter(request):
    """Save entered vCenter settings."""
    try:
        form = VCenterForm(request.POST)
    except:
		form = None
    data = {}

    if form and form.is_valid():
        errors = []

        comp_vc = str(form.cleaned_data[getters.COMP_VC])
        comp_vc_username = str(form.cleaned_data[getters.COMP_VC_USERNAME])
        comp_vc_password = str(form.cleaned_data[getters.COMP_VC_PASSWORD])
        comp_vc_datacenter = str(form.cleaned_data[getters.COMP_VC_DATACENTER])
        comp_vc_cluster = str(form.cleaned_data[getters.COMP_VC_CLUSTER])

        mgmt_vc = str(form.cleaned_data[getters.MGMT_VC])
        mgmt_vc_username = str(form.cleaned_data[getters.MGMT_VC_USERNAME])
        mgmt_vc_password = str(form.cleaned_data[getters.MGMT_VC_PASSWORD])
        mgmt_vc_datacenter = str(form.cleaned_data[getters.MGMT_VC_DATACENTER])
        mgmt_vc_cluster = str(form.cleaned_data[getters.MGMT_VC_CLUSTER])

        vcenter_data = {
            getters.COMP_VC: comp_vc,
            getters.COMP_VC_USERNAME: comp_vc_username,
            getters.COMP_VC_PASSWORD: comp_vc_password,
            getters.COMP_VC_DATACENTER: comp_vc_datacenter,
            getters.COMP_VC_CLUSTER: comp_vc_cluster,
            getters.MGMT_VC: mgmt_vc,
            getters.MGMT_VC_USERNAME: mgmt_vc_username,
            getters.MGMT_VC_PASSWORD: mgmt_vc_password,
            getters.MGMT_VC_DATACENTER: mgmt_vc_datacenter,
            getters.MGMT_VC_CLUSTER: mgmt_vc_cluster,
        }

        # Save vCenter settings to file.
        yaml.dump(settings.VCENTER_SETTINGS, vcenter_data)

        options_data = {
            getters.COMP_VC: [comp_vc],
            getters.COMP_VC_USERNAME: [comp_vc_username],
            getters.COMP_VC_PASSWORD: [comp_vc_password],
            getters.MGMT_VC: [mgmt_vc],
            getters.MGMT_VC_USERNAME: [mgmt_vc_username],
            getters.MGMT_VC_PASSWORD: [mgmt_vc_password],
        }

        # Get management datacenters.
        mgmt_vc_datacenters = getters.get_mgmt_vc_datacenter(
            vcenter=mgmt_vc, username=mgmt_vc_username,
            password=mgmt_vc_password, datacenter='')
        if not mgmt_vc_datacenters:
            errors.append('No management vCenter datacenters found.')
        else:
            options_data[getters.MGMT_VC_DATACENTER] = (
                mgmt_vc_datacenters.keys())

        # Get clusters in the management datacenters.
        mgmt_vc_clusters = None
        if mgmt_vc_datacenters:
            mgmt_vc_clusters = getters.get_mgmt_vc_cluster(
                vcenter=mgmt_vc, username=mgmt_vc_username,
                password=mgmt_vc_password, datacenter=mgmt_vc_datacenter,
                cluster='')
            if not mgmt_vc_clusters:
                errors.append('No management vCenter clusters found.')
            else:
                options_data[getters.MGMT_VC_CLUSTER] = mgmt_vc_clusters.keys()

        if mgmt_vc_clusters:
            # Get hosts in these clusters.
            mgmt_vc_hosts = getters.get_mgmt_vc_hosts(
                vcenter=mgmt_vc, username=mgmt_vc_username,
                password=mgmt_vc_password, datacenter=mgmt_vc_datacenter,
                cluster=mgmt_vc_cluster)
            if not mgmt_vc_hosts:
                errors.append('No management vCenter hosts found.')
            else:
                options_data[getters.MGMT_VC_HOSTS] = mgmt_vc_hosts.keys()

            # Get datastores in these clusters.
            mgmt_vc_datastores = getters.get_mgmt_vc_datastores(
                vcenter=mgmt_vc, username=mgmt_vc_username,
                password=mgmt_vc_password, datacenter=mgmt_vc_datacenter,
                cluster=mgmt_vc_cluster)
            if not mgmt_vc_datastores:
                errors.append('No management vCenter datastores found.')
            else:
                options_data[getters.MGMT_VC_DATASTORES] = mgmt_vc_datastores.keys()

            # Get networks in these clusters.
            mgmt_vc_networks = getters.get_mgmt_vc_networks(
                vcenter=mgmt_vc, username=mgmt_vc_username,
                password=mgmt_vc_password, datacenter=mgmt_vc_datacenter,
                cluster=mgmt_vc_cluster)
            if (not mgmt_vc_networks or
                    len(mgmt_vc_networks) < MIN_MGMT_NETWORKS):
                errors.append(
                    'At least %s management vCenter network%s must be '
                    'available.' % (MIN_MGMT_NETWORKS,
                                    '' if MIN_MGMT_NETWORKS == 1 else 's'))
            else:
                options_data[getters.MGMT_VC_NETWORKS] = mgmt_vc_networks.keys()

        # Get compute datacenters.
        comp_vc_datacenters = getters.get_comp_vc_datacenter(
            vcenter=comp_vc, username=comp_vc_username,
            password=comp_vc_password, datacenter='')
        if not comp_vc_datacenters:
            errors.append('No compute vCenter datacenters found.')
        else:
            options_data[getters.COMP_VC_DATACENTER] = (
                comp_vc_datacenters.keys())

        # Get clusters in the compute datacenters.
        comp_vc_clusters = None
        if comp_vc_datacenters:
            comp_vc_clusters = getters.get_comp_vc_cluster(
                vcenter=comp_vc, username=comp_vc_username,
                password=comp_vc_password, datacenter=comp_vc_datacenter,
                cluster='')
            if not comp_vc_clusters:
                errors.append('No compute vCenter clusters found.')
            else:
                options_data[getters.COMP_VC_CLUSTER] = comp_vc_clusters.keys()

        if comp_vc_clusters:
            # Get hosts in these clusters.
            comp_vc_hosts = getters.get_comp_vc_hosts(
                vcenter=comp_vc, username=comp_vc_username,
                password=comp_vc_password, datacenter=comp_vc_datacenter,
                cluster=comp_vc_cluster)
            if not comp_vc_hosts:
                errors.append('No compute vCenter hosts found.')
            else:
                options_data[getters.COMP_VC_HOSTS] = comp_vc_hosts.keys()

            # Get datastores in these clusters.
            comp_vc_datastores = getters.get_comp_vc_datastores(
                vcenter=comp_vc, username=comp_vc_username,
                password=comp_vc_password, datacenter=comp_vc_datacenter,
                cluster=comp_vc_cluster)
            if not comp_vc_datastores:
                errors.append('No compute vCenter datastores found.')
            else:
                options_data[getters.COMP_VC_DATASTORES] = comp_vc_datastores.keys()

            # Get networks in these clusters.
            comp_vc_networks = getters.get_comp_vc_networks(
                vcenter=comp_vc, username=comp_vc_username,
                password=comp_vc_password, datacenter=comp_vc_datacenter,
                cluster=comp_vc_cluster)
            options_data[getters.COMP_VC_NETWORKS] = comp_vc_networks.keys()

        if errors:
            LOG.error('Unable to save vCenter settings: %s' % errors)
            data['errors'] = errors
        else:
            # Save vCenter field options to file.
            options_filename = settings.INPUT_OPTIONS
            yaml.dump(options_filename, options_data)

            # Rewrite the answer file, to update with new vCenter values and
            # check if previously saved values for dynamically populated fields
            # are no longer valid.
            base_filename = os.path.join(settings.ANSWER_FILE_DIR, settings.ANSWER_FILE_BASE)
            menus = yaml.load(base_filename)

            containers = []
            for menu in menus:
                for menu_name, menu_containers in menu.items():
                    if menu_name == settings.PREPARE_MENU:
                        containers = menu_containers
                        break

            new_answers = {}
            values_cache = {}
            # [{ ... }]
            for container in containers:
                # { 'Container': { ... } }
                for groups in container.values():
                    # [{ ... }]
                    for group in groups:
                        # { 'Group': [...] }
                        for sections in group.values():
                            # [{ ... }]
                            for section in sections:
                                # { 'Section': [...] }
                                for attributes in section.values():
                                    # [{ ... }]
                                    for attr in attributes:
                                        attr_id = attr['id']
                                        opts = attr.get('options', [])
                                        if not isinstance(opts, list):
                                            if opts not in vcenter_data:
                                                break
                                            if opts in values_cache:
                                                new_answers[attr_id] = (
                                                    values_cache[attr_id])
                                            else:
                                                fn_name = 'get_%s_value' % opts
                                                fn = getattr(getters, fn_name)
                                                value = fn()
                                                new_answers[attr_id] = value
                                                values_cache[attr_id] = value

            LOG.debug('New vCenter settings answers: %s' % new_answers)
            answers_filename = '%s/%s' % (settings.ANSWER_FILE_DIR,
                                          settings.ANSWER_FILE_DEFAULT)
            write_answer_file(request, answers_filename,
                              new_answers=new_answers)
    else:
        if form is not None:
            LOG.error('Unable to save vCenter settings: %s' % form.errors)
            data['field_errors'] = form.errors
        else:
            LOG.error('Unable to save vCenter settings: no vCenter form exists!')
            data['field_errors'] = 'No form was created'
    return HttpResponse(json.dumps(data), content_type='application/json')
Beispiel #12
0
def save_vcenter(request):
    """Save entered vCenter settings."""
    try:
        form = VCenterForm(request.POST)
    except:
        form = None
    data = {}

    if form and form.is_valid():
        errors = []

        comp_vc = str(form.cleaned_data[getters.COMP_VC])
        comp_vc_username = str(form.cleaned_data[getters.COMP_VC_USERNAME])
        comp_vc_password = str(form.cleaned_data[getters.COMP_VC_PASSWORD])
        comp_vc_datacenter = str(form.cleaned_data[getters.COMP_VC_DATACENTER])
        comp_vc_cluster = str(form.cleaned_data[getters.COMP_VC_CLUSTER])

        mgmt_vc = str(form.cleaned_data[getters.MGMT_VC])
        mgmt_vc_username = str(form.cleaned_data[getters.MGMT_VC_USERNAME])
        mgmt_vc_password = str(form.cleaned_data[getters.MGMT_VC_PASSWORD])
        mgmt_vc_datacenter = str(form.cleaned_data[getters.MGMT_VC_DATACENTER])
        mgmt_vc_cluster = str(form.cleaned_data[getters.MGMT_VC_CLUSTER])

        vcenter_data = {
            getters.COMP_VC: comp_vc,
            getters.COMP_VC_USERNAME: comp_vc_username,
            getters.COMP_VC_PASSWORD: comp_vc_password,
            getters.COMP_VC_DATACENTER: comp_vc_datacenter,
            getters.COMP_VC_CLUSTER: comp_vc_cluster,
            getters.MGMT_VC: mgmt_vc,
            getters.MGMT_VC_USERNAME: mgmt_vc_username,
            getters.MGMT_VC_PASSWORD: mgmt_vc_password,
            getters.MGMT_VC_DATACENTER: mgmt_vc_datacenter,
            getters.MGMT_VC_CLUSTER: mgmt_vc_cluster,
        }

        # Save vCenter settings to file.
        yaml.dump(settings.VCENTER_SETTINGS, vcenter_data)

        options_data = {
            getters.COMP_VC: [comp_vc],
            getters.COMP_VC_USERNAME: [comp_vc_username],
            getters.COMP_VC_PASSWORD: [comp_vc_password],
            getters.MGMT_VC: [mgmt_vc],
            getters.MGMT_VC_USERNAME: [mgmt_vc_username],
            getters.MGMT_VC_PASSWORD: [mgmt_vc_password],
        }

        # Get management datacenters.
        mgmt_vc_datacenters = getters.get_mgmt_vc_datacenter(
            vcenter=mgmt_vc,
            username=mgmt_vc_username,
            password=mgmt_vc_password,
            datacenter='')
        if not mgmt_vc_datacenters:
            errors.append('No management vCenter datacenters found.')
        else:
            options_data[getters.MGMT_VC_DATACENTER] = (
                mgmt_vc_datacenters.keys())

        # Get clusters in the management datacenters.
        mgmt_vc_clusters = None
        if mgmt_vc_datacenters:
            mgmt_vc_clusters = getters.get_mgmt_vc_cluster(
                vcenter=mgmt_vc,
                username=mgmt_vc_username,
                password=mgmt_vc_password,
                datacenter=mgmt_vc_datacenter,
                cluster='')
            if not mgmt_vc_clusters:
                errors.append('No management vCenter clusters found.')
            else:
                options_data[getters.MGMT_VC_CLUSTER] = mgmt_vc_clusters.keys()

        if mgmt_vc_clusters:
            # Get hosts in these clusters.
            mgmt_vc_hosts = getters.get_mgmt_vc_hosts(
                vcenter=mgmt_vc,
                username=mgmt_vc_username,
                password=mgmt_vc_password,
                datacenter=mgmt_vc_datacenter,
                cluster=mgmt_vc_cluster)
            if not mgmt_vc_hosts:
                errors.append('No management vCenter hosts found.')
            else:
                options_data[getters.MGMT_VC_HOSTS] = mgmt_vc_hosts.keys()

            # Get datastores in these clusters.
            mgmt_vc_datastores = getters.get_mgmt_vc_datastores(
                vcenter=mgmt_vc,
                username=mgmt_vc_username,
                password=mgmt_vc_password,
                datacenter=mgmt_vc_datacenter,
                cluster=mgmt_vc_cluster)
            if not mgmt_vc_datastores:
                errors.append('No management vCenter datastores found.')
            else:
                options_data[
                    getters.MGMT_VC_DATASTORES] = mgmt_vc_datastores.keys()

            # Get networks in these clusters.
            mgmt_vc_networks = getters.get_mgmt_vc_networks(
                vcenter=mgmt_vc,
                username=mgmt_vc_username,
                password=mgmt_vc_password,
                datacenter=mgmt_vc_datacenter,
                cluster=mgmt_vc_cluster)
            if (not mgmt_vc_networks
                    or len(mgmt_vc_networks) < MIN_MGMT_NETWORKS):
                errors.append(
                    'At least %s management vCenter network%s must be '
                    'available.' %
                    (MIN_MGMT_NETWORKS, '' if MIN_MGMT_NETWORKS == 1 else 's'))
            else:
                options_data[
                    getters.MGMT_VC_NETWORKS] = mgmt_vc_networks.keys()

        # Get compute datacenters.
        comp_vc_datacenters = getters.get_comp_vc_datacenter(
            vcenter=comp_vc,
            username=comp_vc_username,
            password=comp_vc_password,
            datacenter='')
        if not comp_vc_datacenters:
            errors.append('No compute vCenter datacenters found.')
        else:
            options_data[getters.COMP_VC_DATACENTER] = (
                comp_vc_datacenters.keys())

        # Get clusters in the compute datacenters.
        comp_vc_clusters = None
        if comp_vc_datacenters:
            comp_vc_clusters = getters.get_comp_vc_cluster(
                vcenter=comp_vc,
                username=comp_vc_username,
                password=comp_vc_password,
                datacenter=comp_vc_datacenter,
                cluster='')
            if not comp_vc_clusters:
                errors.append('No compute vCenter clusters found.')
            else:
                options_data[getters.COMP_VC_CLUSTER] = comp_vc_clusters.keys()

        if comp_vc_clusters:
            # Get hosts in these clusters.
            comp_vc_hosts = getters.get_comp_vc_hosts(
                vcenter=comp_vc,
                username=comp_vc_username,
                password=comp_vc_password,
                datacenter=comp_vc_datacenter,
                cluster=comp_vc_cluster)
            if not comp_vc_hosts:
                errors.append('No compute vCenter hosts found.')
            else:
                options_data[getters.COMP_VC_HOSTS] = comp_vc_hosts.keys()

            # Get datastores in these clusters.
            comp_vc_datastores = getters.get_comp_vc_datastores(
                vcenter=comp_vc,
                username=comp_vc_username,
                password=comp_vc_password,
                datacenter=comp_vc_datacenter,
                cluster=comp_vc_cluster)
            if not comp_vc_datastores:
                errors.append('No compute vCenter datastores found.')
            else:
                options_data[
                    getters.COMP_VC_DATASTORES] = comp_vc_datastores.keys()

            # Get networks in these clusters.
            comp_vc_networks = getters.get_comp_vc_networks(
                vcenter=comp_vc,
                username=comp_vc_username,
                password=comp_vc_password,
                datacenter=comp_vc_datacenter,
                cluster=comp_vc_cluster)
            options_data[getters.COMP_VC_NETWORKS] = comp_vc_networks.keys()

        if errors:
            LOG.error('Unable to save vCenter settings: %s' % errors)
            data['errors'] = errors
        else:
            # Save vCenter field options to file.
            options_filename = settings.INPUT_OPTIONS
            yaml.dump(options_filename, options_data)

            # Rewrite the answer file, to update with new vCenter values and
            # check if previously saved values for dynamically populated fields
            # are no longer valid.
            base_filename = os.path.join(settings.ANSWER_FILE_DIR,
                                         settings.ANSWER_FILE_BASE)
            menus = yaml.load(base_filename)

            containers = []
            for menu in menus:
                for menu_name, menu_containers in menu.items():
                    if menu_name == settings.PREPARE_MENU:
                        containers = menu_containers
                        break

            new_answers = {}
            values_cache = {}
            # [{ ... }]
            for container in containers:
                # { 'Container': { ... } }
                for groups in container.values():
                    # [{ ... }]
                    for group in groups:
                        # { 'Group': [...] }
                        for sections in group.values():
                            # [{ ... }]
                            for section in sections:
                                # { 'Section': [...] }
                                for attributes in section.values():
                                    # [{ ... }]
                                    for attr in attributes:
                                        attr_id = attr['id']
                                        opts = attr.get('options', [])
                                        if not isinstance(opts, list):
                                            if opts not in vcenter_data:
                                                break
                                            if opts in values_cache:
                                                new_answers[attr_id] = (
                                                    values_cache[attr_id])
                                            else:
                                                fn_name = 'get_%s_value' % opts
                                                fn = getattr(getters, fn_name)
                                                value = fn()
                                                new_answers[attr_id] = value
                                                values_cache[attr_id] = value

            LOG.debug('New vCenter settings answers: %s' % new_answers)
            answers_filename = '%s/%s' % (settings.ANSWER_FILE_DIR,
                                          settings.ANSWER_FILE_DEFAULT)
            write_answer_file(request,
                              answers_filename,
                              new_answers=new_answers)
    else:
        if form is not None:
            LOG.error('Unable to save vCenter settings: %s' % form.errors)
            data['field_errors'] = form.errors
        else:
            LOG.error(
                'Unable to save vCenter settings: no vCenter form exists!')
            data['field_errors'] = 'No form was created'
    return HttpResponse(json.dumps(data), content_type='application/json')