Skip to content

Commit

Permalink
Convert the subnet form to DDF
Browse files Browse the repository at this point in the history
  • Loading branch information
skateman authored and DavidResende0 committed May 14, 2021
1 parent bed0cca commit 61f092e
Show file tree
Hide file tree
Showing 19 changed files with 394 additions and 670 deletions.
193 changes: 0 additions & 193 deletions app/controllers/cloud_subnet_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,73 +35,10 @@ def button
end

def new
assert_privileges("cloud_subnet_new")
assert_privileges("ems_network_show_list")
assert_privileges("cloud_tenant_show_list")
assert_privileges("cloud_network_show_list")

@in_a_form = true
drop_breadcrumb(:name => _("Add New Subnet"), :url => "/cloud_subnet/new")
end

def create
assert_privileges("cloud_subnet_new")
case params[:button]
when "cancel"
javascript_redirect(:action => 'show_list',
:flash_msg => _("Creation of a Cloud Subnet was cancelled by the user"))

when "add"
@subnet = CloudSubnet.new
begin
options = new_form_params
ems = ExtManagementSystem.find(options[:ems_id])
if CloudSubnet.class_by_ems(ems).supports_create?
options.delete(:ems_id)
task_id = ems.create_cloud_subnet_queue(session[:userid], options)

if task_id.kind_of?(Integer)
initiate_wait_for_task(:task_id => task_id, :action => "create_finished")
else
javascript_flash(
:text => _("Cloud Subnet creation: Task start failed"),
:severity => :error,
:spinner_off => true
)
end
else
@in_a_form = true
add_flash(_(CloudSubnet.unsupported_reason(:create)), :error)
drop_breadcrumb(:name => _("Add new Cloud Subnet "), :url => "/subnet/new")
javascript_flash
end
rescue ArgumentError => err
javascript_flash(
:text => _("Parameter Error: %{error_message}") % {:error_message => err.message},
:severity => :error,
:spinner_off => true
)
end
end
end

def create_finished
task_id = session[:async][:params][:task_id]
subnet_name = session[:async][:params][:name]
task = MiqTask.find(task_id)
if MiqTask.status_ok?(task.status)
add_flash(_("Cloud Subnet \"%{name}\" created") % {:name => subnet_name})
else
add_flash(_("Unable to create Cloud Subnet: %{details}") %
{ :name => subnet_name, :details => task.message }, :error)
end

@breadcrumbs&.pop
session[:edit] = nil
flash_to_session
javascript_redirect(:action => "show_list")
end

def delete_subnets
assert_privileges("cloud_subnet_delete")
subnets = find_records_with_rbac(CloudSubnet, checked_or_params)
Expand Down Expand Up @@ -138,7 +75,6 @@ def delete_subnets

def edit
params[:id] = checked_item_id if params[:id].blank?
assert_privileges("cloud_subnet_edit")
@subnet = find_record_with_rbac(CloudSubnet, params[:id])
@in_a_form = true
drop_breadcrumb(
Expand All @@ -147,56 +83,6 @@ def edit
)
end

def update
assert_privileges("cloud_subnet_edit")
@subnet = find_record_with_rbac(CloudSubnet, params[:id])
case params[:button]
when "cancel"
flash_and_redirect(_("Edit of Subnet \"%{name}\" was cancelled by the user") % {:name => @subnet.name})

when "save"
if @subnet.supports_create?
begin
options = changed_form_params
task_id = @subnet.update_cloud_subnet_queue(session[:userid], options)

if task_id.kind_of?(Integer)
initiate_wait_for_task(:task_id => task_id, :action => "update_finished")
else
javascript_flash(
:text => _("Cloud Subnet update failed: Task start failed"),
:severity => :error,
:spinner_off => true
)
end
rescue ArgumentError => err
javascript_flash(
:text => _("Parameter Error: %{error_message}") % {:error_message => err.message},
:severity => :error,
:spinner_off => true
)
end
else
add_flash(_("Couldn't initiate update of Cloud Subnet \"%{name}\": %{details}") % {
:name => @subnet.name,
:details => @subnet.unsupported_reason(:update)
}, :error)
end
end
end

def update_finished
task_id = session[:async][:params][:task_id]
subnet_name = session[:async][:params][:name]
task = MiqTask.find(task_id)
if MiqTask.status_ok?(task.status)
flash_and_redirect(_("Cloud Subnet \"%{name}\" updated") % {:name => subnet_name})
else
flash_and_redirect(_("Unable to update Cloud Subnet \"%{name}\": %{details}") % {:name => subnet_name,
:details => task.message}, :error)
end
end

def download_data
assert_privileges('cloud_subnet_view')
super
Expand All @@ -222,85 +108,6 @@ def switch_to_bol(option)
end
end

def parse_allocation_pools(option)
return [] unless option

option.lines.map do |pool|
start_addr, end_addr, extra_entry = pool.split(",")
raise ArgumentError, _("Too few addresses in line. Proper format is start_ip_address,end_ip_address (one Allocation Pool per line)") unless end_addr
raise ArgumentError, _("Too many addresses in line. Proper format is start_ip_address,end_ip_address (one Allocation Pool per line)") if extra_entry

{"start" => start_addr.strip, "end" => end_addr.strip}
end
end

def parse_host_routes(option)
return [] unless option

option.lines.map do |route|
dest_addr, nexthop_addr, extra_entry = route.split(",")
raise ArgumentError, _("Too few entries in line. Proper format is destination_cidr,nexthop (one Host Route per line)") unless nexthop_addr
raise ArgumentError, _("Too many entries in line. Proper format is destination_cidr,nexthop (one Host Route per line)") if extra_entry

{"destination" => dest_addr.strip, "nexthop" => nexthop_addr.strip}
end
end

def parse_dns_nameservers(option)
return [] unless option

option.lines.map do |nameserver|
one_nameserver, extra_entry = nameserver.strip.split(/\s+|,/)
raise ArgumentError, _("One DNS Name Server per line is required.") if !one_nameserver || extra_entry

one_nameserver
end
end

def changed_form_params
# Allowed fields for update: name, enable_dhcp, dns_nameservers, allocation_pools, host_routes, gateway_ip
options = {}
options[:name] = params[:name] unless @subnet.name == params[:name]

# Provider to automatically assign gateway address unless provided
unless @subnet.gateway == params[:gateway]
options[:gateway_ip] = params[:gateway].presence
end

unless @subnet.dhcp_enabled == switch_to_bol(params[:dhcp_enabled])
options[:enable_dhcp] = switch_to_bol(params[:dhcp_enabled])
end
unless @subnet.allocation_pools == (pools = parse_allocation_pools(params[:allocation_pools])) || (@subnet.allocation_pools.blank? && pools.blank?)
options[:allocation_pools] = pools
end
unless @subnet.host_routes == (routes = parse_host_routes(params[:host_routes])) || (@subnet.host_routes.blank? && routes.blank?)
options[:host_routes] = routes
end
unless @subnet.dns_nameservers == (nameservers = parse_dns_nameservers(params[:dns_nameservers])) || (@subnet.dns_nameservers.blank? && nameservers.blank?)
options[:dns_nameservers] = nameservers
end
options
end

def new_form_params
params[:network_protocol] ||= "ipv4"
params[:dhcp_enabled] ||= false
options = {}
copy_params_if_present(options, params, %i[name ems_id cidr network_id availability_zone_id ipv6_router_advertisement_mode ipv6_address_mode network_group_id parent_cloud_subnet_id])
# Provider to automatically assign gateway address unless provided
if params[:gateway]
options[:gateway_ip] = params[:gateway].presence
end
options[:ip_version] = /4/.match?(params[:network_protocol]) ? 4 : 6
options[:cloud_tenant] = find_record_with_rbac(CloudTenant, params[:cloud_tenant][:id]) if params.fetch_path(:cloud_tenant, :id)
options[:enable_dhcp] = params[:dhcp_enabled]
# TODO: Add dns_nameservers, allocation_pools, host_routes
options[:allocation_pools] = parse_allocation_pools(params[:allocation_pools]) if params[:allocation_pools].present?
options[:dns_nameservers] = parse_dns_nameservers(params[:dns_nameservers]) if params[:dns_nameservers].present?
options[:host_routes] = parse_host_routes(params[:host_routes]) if params[:host_routes].present?
options
end

# dispatches operations to multiple subnets
def process_cloud_subnets(subnets, operation)
return if subnets.empty?
Expand Down
29 changes: 26 additions & 3 deletions app/controllers/ops_controller/settings/zones.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ def zone_edit
unless @edit[:new][:description]
add_flash(_("Description can't be blank"), :error)
end
unless @edit[:new][:password] == @edit[:new][:verify]
add_flash(_('Password and Verify Password fields do not match'), :error)
end

# This is needed for cases when more than one required field is missing or is not correct, to prevent rendering same flash messages
if @flash_array
Expand All @@ -36,8 +39,7 @@ def zone_edit
end

zone_set_record_vars(@zone)
@edit[:errors] = []
if @zone.save
if valid_record?(@zone) && @zone.save
AuditEvent.success(build_created_audit(@zone, @edit))
if params[:button] == "save"
add_flash(_("Zone \"%{name}\" was saved") % {:name => @edit[:new][:name]})
Expand Down Expand Up @@ -113,13 +115,30 @@ def zone_set_record_vars(zone, mode = nil)
zone.settings ||= {}
zone.settings[:proxy_server_ip] = @edit[:new][:proxy_server_ip]
zone.settings[:concurrent_vm_scans] = @edit[:new][:concurrent_vm_scans]

zone.update_authentication({:windows_domain => {:userid => @edit[:new][:userid], :password => @edit[:new][:password]}}, {:save => (mode != :validate)})
end

# Validate the zone record fields
def valid_record?(zone)
valid = true
@edit[:errors] = []
if zone.authentication_password.present? && zone.authentication_userid.blank?
@edit[:errors].push(_("Username must be entered if Password is entered"))
valid = false
end
if @edit[:new][:password] != @edit[:new][:verify]
@edit[:errors].push(_("Password and Verify Password fields do not match"))
valid = false
end
valid
end

# Get variables from zone edit form
def zone_get_form_vars
@zone = @edit[:zone_id] ? Zone.find(@edit[:zone_id]) : Zone.new

copy_params_if_present(@edit[:new], params, %i[name description proxy_server_ip])
copy_params_if_present(@edit[:new], params, %i[name description proxy_server_ip userid password verify])
@edit[:new][:concurrent_vm_scans] = params[:max_scans].to_i if params[:max_scans]

set_verify_status
Expand All @@ -145,6 +164,10 @@ def zone_set_form_vars
@edit[:new][:proxy_server_ip] = @zone.settings ? @zone.settings[:proxy_server_ip] : nil
@edit[:new][:concurrent_vm_scans] = @zone.settings ? @zone.settings[:concurrent_vm_scans].to_i : 0

@edit[:new][:userid] = @zone.authentication_userid(:windows_domain)
@edit[:new][:password] = @zone.authentication_password(:windows_domain)
@edit[:new][:verify] = @zone.authentication_password(:windows_domain)

session[:verify_ems_status] = nil
set_verify_status

Expand Down
100 changes: 100 additions & 0 deletions app/javascript/components/subnet-form/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';

import MiqFormRenderer from '@@ddf';
import createSchema from './subnet-form.schema';
import miqRedirectBack from '../../helpers/miq-redirect-back';
import { API } from '../../http_api';

const SubnetForm = ({ recordId }) => {
const [{ initialValues, isLoading, fields }, setState] = useState({ isLoading: !!recordId, fields: [] });
const submitLabel = !!recordId ? __('Save') : __('Add');

const loadSchema = (appendState = {}) => ({ data: { form_schema: { fields } } }) => {
if (!!recordId && appendState.initialValues.type === 'ManageIQ::Providers::Openstack::NetworkManager::CloudSubnet') {
Object.assign(fields[0], {isDisabled: true});
Object.assign(fields[1], {isDisabled: true});
Object.assign(fields[4], {isDisabled: true});
}
setState((state) => ({
...state,
...appendState,
fields,
}));
};

useEffect(() => {
if (recordId) {
API.get(`/api/cloud_subnets/${recordId}`).then((initialValues) => {
if(typeof initialValues.cloud_network_id ==="string") {
initialValues.cloud_network_id=Number(initialValues.cloud_network_id);
}
if(typeof initialValues.cloud_tenant_id ==="string") {
initialValues.cloud_tenant_id=Number(initialValues.cloud_tenant_id);
}
API.options(`/api/cloud_subnets?ems_id=${initialValues.ems_id}`).then(loadSchema({ initialValues, isLoading: false }));
});
}
}, [recordId]);

const onSubmit = (values) => {
API.get(`/api/providers/${values.ems_id}`).then(({ type }) => {
if (type === 'ManageIQ::Providers::Openstack::NetworkManager') {
if (values.ip_version === undefined) {
values.ip_version = '4';
}
if (values.dhcp_enabled === undefined) {
values.dhcp_enabled = false;
}
values.enable_dhcp = values.dhcp_enabled;
delete values.dhcp_enabled;
delete Object.assign(values, values.extra_attributes).extra_attributes;

API.get(`/api/cloud_networks/${values.cloud_network_id}`).then( ({ ems_ref }) => {
values.network_id = ems_ref;
miqSparkleOn();
const request = recordId ? API.patch(`/api/cloud_subnets/${recordId}`, values) : API.post('/api/cloud_subnets', values);

request.then(() => {
const message = sprintf(recordId
? __('Modification of Cloud Subnet %s has been successfully queued')
: __('Add of Cloud Subnet "%s" has been successfully queued.'),
values.name);

miqRedirectBack(message, 'success', '/cloud_subnet/show_list');
}).catch(miqSparkleOff);
});
}
});
};

const onCancel = () => {
const message = sprintf(
recordId
? __('Edit of Cloud Subnet "%s" was canceled by the user.')
: __('Creation of new Cloud Subnet was canceled by the user.'),
initialValues && initialValues.name,
);
miqRedirectBack(message, 'warning', '/cloud_subnet/show_list');
};

return !isLoading && (
<MiqFormRenderer
schema={createSchema(!!recordId, fields, loadSchema)}
initialValues={initialValues}
canReset={!!recordId}
onSubmit={onSubmit}
onCancel={onCancel}
buttonsLabels={{ submitLabel }}
/>
);
};

SubnetForm.propTypes = {
recordId: PropTypes.string,
};
SubnetForm.defaultProps = {
recordId: undefined,
};

export default SubnetForm;
Loading

0 comments on commit 61f092e

Please sign in to comment.