From 92978922a61510a785346ca07b38a98aba2e3891 Mon Sep 17 00:00:00 2001 From: chitra607 Date: Thu, 17 Jul 2025 06:42:51 +0000 Subject: [PATCH 1/5] Openshift volume Attach/Detach --- .../application_controller/explorer.rb | 3 + app/controllers/vm_common.rb | 38 ++++++ app/controllers/vm_infra_controller.rb | 28 ++++ .../button/vm_attach_volume.rb | 6 + .../button/vm_detach_volume.rb | 6 + .../application_helper/toolbar/x_vm_center.rb | 14 ++ .../components/vm-infra/add-volume.jsx | 129 ++++++++++++++++++ .../components/vm-infra/add-volume.schema.js | 77 +++++++++++ .../components/vm-infra/remove-volume.jsx | 102 ++++++++++++++ .../vm-infra/remove-volume.schema.js | 26 ++++ .../packs/component-definitions-common.js | 4 + app/views/vm_common/_add_volume.html.haml | 6 + app/views/vm_common/_remove_volume.html.haml | 7 + config/routes.rb | 4 + 14 files changed, 450 insertions(+) create mode 100644 app/helpers/application_helper/button/vm_attach_volume.rb create mode 100644 app/helpers/application_helper/button/vm_detach_volume.rb create mode 100644 app/javascript/components/vm-infra/add-volume.jsx create mode 100644 app/javascript/components/vm-infra/add-volume.schema.js create mode 100644 app/javascript/components/vm-infra/remove-volume.jsx create mode 100644 app/javascript/components/vm-infra/remove-volume.schema.js create mode 100644 app/views/vm_common/_add_volume.html.haml create mode 100644 app/views/vm_common/_remove_volume.html.haml diff --git a/app/controllers/application_controller/explorer.rb b/app/controllers/application_controller/explorer.rb index 51502c17cad..c34ed80d815 100644 --- a/app/controllers/application_controller/explorer.rb +++ b/app/controllers/application_controller/explorer.rb @@ -61,6 +61,9 @@ def x_history 'remove_security_group' => :s2, 'rename' => :s2, + 'add_volume' => :s2, + 'remove_volume' => :s2, + # specials 'perf' => :show, 'download_pdf' => :show, diff --git a/app/controllers/vm_common.rb b/app/controllers/vm_common.rb index 1fa5c734741..3d0718049c0 100644 --- a/app/controllers/vm_common.rb +++ b/app/controllers/vm_common.rb @@ -25,6 +25,32 @@ def textual_summary_flash_list helper_method :disable_check? end + def add_volume + assert_privileges("vm_common_add_volume") + @record = find_record_with_rbac(VmOrTemplate, params[:id]) + @edit ||= {} + @in_a_form = true + + if @explorer + @refresh_partial = "vm_common/add_volume" + @edit[:explorer] = true + end + end + alias_method :instance_add_volume, :add_volume + + def remove_volume + assert_privileges("vm_common_remove_volume") + @record = find_record_with_rbac(VmOrTemplate, params[:id]) + @edit ||= {} + @in_a_form = true + + if @explorer + @refresh_partial = "vm_common/remove_volume" + @edit[:explorer] = true + end + end + alias_method :instance_remove_volume, :remove_volume + # handle buttons pressed on the button bar def button @edit = session[:edit] # Restore @edit for adv search box @@ -1297,6 +1323,18 @@ def set_right_cell_vars(options = {}) partial = "layouts/tl_show" header = _("Timelines for %{virtual_machine} \"%{name}\"") % {:virtual_machine => ui_lookup(:table => table), :name => name} action = nil + when "add_volume", "instance_add_volume" + partial = "vm_common/add_volume" + header = _("Add Volume to %{vm_or_template} \"%{name}\"") % { + :vm_or_template => ui_lookup(:table => table), + :name => name + } + when "remove_volume", "instance_remove_volume" + partial = "vm_common/remove_volume" + header = _("Remove Volume %{vm_or_template} \"%{name}\"") % { + :vm_or_template => ui_lookup(:table => table), + :name => name + } else # now take care of links on summary screen partial = if @showtype == "details" diff --git a/app/controllers/vm_infra_controller.rb b/app/controllers/vm_infra_controller.rb index aab70635974..0aabd975a32 100644 --- a/app/controllers/vm_infra_controller.rb +++ b/app/controllers/vm_infra_controller.rb @@ -19,6 +19,34 @@ def index redirect_to(:action => 'explorer') end + def persistentvolumeclaims + @record = find_record_with_rbac(VmOrTemplate, params[:id]) + + pvcs = @record.persistentvolumeclaims(@record) + + render :json => { + :resources => pvcs, + :vm_name => @record.name, + :vm_namespace => @record.location + } + rescue => e + render :json => { :error => e.message }, :status => :internal_server_error + end + + def attached_volumes + @record = find_record_with_rbac(VmOrTemplate, params[:id]) + + attached = @record.attached_volumes(@record) + + render json: { + resources: attached, + vm_name: @record.name, + vm_namespace: @record.location + } + rescue => e + render :json => { :error => e.message }, :status => :internal_server_error + end + private def features diff --git a/app/helpers/application_helper/button/vm_attach_volume.rb b/app/helpers/application_helper/button/vm_attach_volume.rb new file mode 100644 index 00000000000..cf5fcef5e0b --- /dev/null +++ b/app/helpers/application_helper/button/vm_attach_volume.rb @@ -0,0 +1,6 @@ +class ApplicationHelper::Button::VmAttachVolume < ApplicationHelper::Button::Basic + needs :@record + def visible? + @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) + end +end \ No newline at end of file diff --git a/app/helpers/application_helper/button/vm_detach_volume.rb b/app/helpers/application_helper/button/vm_detach_volume.rb new file mode 100644 index 00000000000..1a6af3dad55 --- /dev/null +++ b/app/helpers/application_helper/button/vm_detach_volume.rb @@ -0,0 +1,6 @@ +class ApplicationHelper::Button::VmDetachVolume < ApplicationHelper::Button::Basic + needs :@record + def visible? + @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) + end +end diff --git a/app/helpers/application_helper/toolbar/x_vm_center.rb b/app/helpers/application_helper/toolbar/x_vm_center.rb index a5ffa8b54ec..0c1c7d48561 100644 --- a/app/helpers/application_helper/toolbar/x_vm_center.rb +++ b/app/helpers/application_helper/toolbar/x_vm_center.rb @@ -87,6 +87,20 @@ class ApplicationHelper::Toolbar::XVmCenter < ApplicationHelper::Toolbar::Basic t, :klass => ApplicationHelper::Button::VmSnapshotAdd ), + button( + :instance_add_volume, + 'fa fa-hdd-o fa-lg', + t = N_('Attach Volume'), + t, + :klass => ApplicationHelper::Button::VmAttachVolume + ), + button( + :instance_remove_volume, + 'fa fa-trash-o fa-lg', + t = N_('Detach Volume'), + t, + :klass => ApplicationHelper::Button::VmDetachVolume + ), ] ), ]) diff --git a/app/javascript/components/vm-infra/add-volume.jsx b/app/javascript/components/vm-infra/add-volume.jsx new file mode 100644 index 00000000000..9dc251ec390 --- /dev/null +++ b/app/javascript/components/vm-infra/add-volume.jsx @@ -0,0 +1,129 @@ +import React, { useState, useEffect, useMemo } from "react"; +import PropTypes from "prop-types"; +import { Grid } from "carbon-components-react"; +import MiqFormRenderer from "../../forms/data-driven-form"; +import { API } from "../../http_api"; +import createSchema from "./add-volume.schema"; +import miqRedirectBack from "../../helpers/miq-redirect-back"; + +const AddVolumeForm = ({ recordId, redirect }) => { + const [state, setState] = useState({ + isLoading: true, + volumes: [], + }); + + const [isSubmitDisabled, setSubmitDisabled] = useState(true); + + useEffect(() => { + const fetchPersistentVolumeClaims = async () => { + try { + setState(prev => ({ ...prev, isLoading: true, error: null })); + + // Use the correct route for your Rails controller + const response = await fetch(`/vm_infra/${recordId}/persistentvolumeclaims`); + const data = await response.json(); + + if (!response.ok) { + throw new Error((data.error && data.error.message) || 'Failed to fetch persistent volume claims'); + } + + setState(prev => ({ + ...prev, + isLoading: false, + volumes: data.resources || [], + vmInfo: { + name: data.vm_name, + namespace: data.vm_namespace + } + })); + } catch (error) { + console.error('Error fetching PVCs:', error); + setState(prev => ({ + ...prev, + isLoading: false, + error: error.message, + volumes: [] + })); + } + }; + + fetchPersistentVolumeClaims(); +}, [recordId]); + + const schema = useMemo(() => createSchema(state.volumes), [state.volumes]); + + const onFormChange = (values) => { + if (values.volumeSourceType === "existing") { + setSubmitDisabled(!values.pvcName); + } else if (values.volumeSourceType === "new") { + setSubmitDisabled(!values.newVolumeName || !values.newVolumeSize); + } else { + setSubmitDisabled(true); + } + }; + + const onSubmit = (values) => { + const { volumeSourceType } = values; + + let payload; + + if (volumeSourceType === "existing") { + const volumeNameFinal = + values.volumeName && values.volumeName.trim() + ? values.volumeName.trim() + : values.pvcName; + + payload = { + action: "attach", + resource: { + pvc_name: values.pvcName, + volume_name: volumeNameFinal, + vm_id: recordId + } + }; + } else { + payload = { + action: "create_and_attach_volume", + resource: { + volume_name: values.newVolumeName.trim(), + volume_size: values.newVolumeSize.trim(), + vm_id: recordId + }, + }; + } + + const request = API.post(`/api/container_volumes/${recordId}`, payload); + + request.then(() => { + const message = sprintf( + __('Volume processed successfully.') + ); + miqRedirectBack(message, 'success', redirect); + }).catch((error) => { + miqRedirectBack(error.message || __("Failed to attach volume"), "error", redirect); + }).finally(miqSparkleOff); + + }; + + const onCancel = () => + miqRedirectBack(__("Add Volume was cancelled by the user"), "warning", redirect); + + return state.isLoading ? null : ( + + + + ); +}; + +AddVolumeForm.propTypes = { + recordId: PropTypes.string.isRequired, + redirect: PropTypes.string.isRequired, +}; + +export default AddVolumeForm; \ No newline at end of file diff --git a/app/javascript/components/vm-infra/add-volume.schema.js b/app/javascript/components/vm-infra/add-volume.schema.js new file mode 100644 index 00000000000..ca71fa84dd4 --- /dev/null +++ b/app/javascript/components/vm-infra/add-volume.schema.js @@ -0,0 +1,77 @@ +import { componentTypes } from "@@ddf"; + +const createSchema = (volumes = []) => ({ + fields: [ + { + component: componentTypes.RADIO, + name: "volumeSourceType", + label: __("Volume Source Type"), + isRequired: true, + options: [ + { label: __("Select Existing PVC"), value: "existing" }, + { label: __("Create New PVC"), value: "new" }, + ], + initialValue: "existing", + }, + // Existing PVC selection + { + component: componentTypes.SELECT, + name: "pvcName", + id: "pvcName", + label: __("Select Persistent Volume Claim"), + placeholder: volumes.length > 0 ? __("Select PVC") : __("No PVCs available"), + options: volumes.length > 0 + ? [ + { label: __("Select PVC"), value: null, isDisabled: true }, + ...volumes.map(({ metadata }) => ({ + label: metadata.name, + value: metadata.name, + })), + ] + : [{ label: __("No PVCs available"), value: "", isDisabled: true }], + condition: { + when: "volumeSourceType", + is: "existing", + }, + isRequired: true, + validate: [{ type: "required", message: __("PVC selection is required") }], + }, + + + // New volume name + { + component: componentTypes.TEXT_FIELD, + name: "newVolumeName", + id: "newVolumeName", + label: __("New Volume Name"), + isRequired: true, + condition: { + when: "volumeSourceType", + is: "new", + }, + validate: [{ type: "required", message: __("Volume name is required") }], + }, + // New volume size + { + component: componentTypes.TEXT_FIELD, + name: "newVolumeSize", + id: "newVolumeSize", + label: __("New Volume Size (e.g., 3Gi)"), + isRequired: true, + condition: { + when: "volumeSourceType", + is: "new", + }, + validate: [ + { type: "required", message: __("Volume size is required") }, + { + type: "pattern", + pattern: "^[0-9]+Gi$", + message: __("Size must be in Gi format (e.g., 3Gi)"), + }, + ], + }, + ], +}); + +export default createSchema; diff --git a/app/javascript/components/vm-infra/remove-volume.jsx b/app/javascript/components/vm-infra/remove-volume.jsx new file mode 100644 index 00000000000..e6750338992 --- /dev/null +++ b/app/javascript/components/vm-infra/remove-volume.jsx @@ -0,0 +1,102 @@ +import React, { useState, useEffect, useMemo } from "react"; +import PropTypes from "prop-types"; +import { Grid } from "carbon-components-react"; +import MiqFormRenderer from "../../forms/data-driven-form"; +import { API } from "../../http_api"; +import miqRedirectBack from "../../helpers/miq-redirect-back"; +import createDetachSchema from "./remove-volume.schema"; + +const DetachVolumeForm = ({ recordId, redirect }) => { + const [state, setState] = useState({ + isLoading: true, + volumes: [], + }); + + const [isSubmitDisabled, setSubmitDisabled] = useState(true); + + useEffect(() => { + const fetchVolumes = async () => { + try { + setState(prev => ({ ...prev, isLoading: true, error: null })); + + const response = await fetch(`/vm_infra/${recordId}/attached_volumes`); + const data = await response.json(); + + if (!response.ok) { + throw new Error((data.error && data.error.message) || 'Failed to fetch attached volumes'); + } + + setState(prev => ({ + ...prev, + isLoading: false, + volumes: data.resources || [], + })); + } catch (error) { + console.error('Error fetching volumes:', error); + setState(prev => ({ + ...prev, + isLoading: false, + error: error.message, + volumes: [] + })); + } + }; + + fetchVolumes(); + }, [recordId]); + + const schema = useMemo(() => createDetachSchema(state.volumes), [state.volumes]); + + const onFormChange = (values) => { + setSubmitDisabled(!values.volumeName); + }; + + const onSubmit = (values) => { + miqSparkleOn(); + + let payload = { + action: "detach", + resource: { + volume_name: values.volumeName.trim(), + vm_id: recordId + }, + }; + + const request = API.post(`/api/container_volumes/${recordId}`, payload) + request.then(() => { + const message = sprintf( + __('Detachment of Container Volume has been successfully queued.') + ); + miqRedirectBack(message, 'success', redirect); + }).catch((error) => { + miqRedirectBack(error.message || __("Failed to detach volume"), "error", redirect); + }).finally(miqSparkleOff); + + }; + + const onCancel = () => { + miqSparkleOn(); + const message = sprintf(__('Detach Volume was cancelled by the user.')); + miqRedirectBack(message, 'warning', redirect); + }; + + return state.isLoading ? null : ( + + + + ); +}; + +DetachVolumeForm.propTypes = { + recordId: PropTypes.string.isRequired, + redirect: PropTypes.string.isRequired, +}; + +export default DetachVolumeForm; diff --git a/app/javascript/components/vm-infra/remove-volume.schema.js b/app/javascript/components/vm-infra/remove-volume.schema.js new file mode 100644 index 00000000000..cd2ea2cca3c --- /dev/null +++ b/app/javascript/components/vm-infra/remove-volume.schema.js @@ -0,0 +1,26 @@ +import { componentTypes } from "@@ddf"; + +const createDetachSchema = (volumes = []) => ({ + fields: [ + { + component: componentTypes.SELECT, + name: "volumeName", + id: "volumeName", + label: __("Select Volume to Detach"), + placeholder: volumes.length > 0 ? __("Select Volume") : __("No Volumes Available"), + options: volumes.length > 0 + ? [ + { label: __("Select Volume"), value: "", isDisabled: true }, + ...volumes.map(({ metadata }) => ({ + label: metadata.name, + value: metadata.name, + })), + ] + : [{ label: __("No Volumes Available"), value: "", isDisabled: true }], + isRequired: true, + validate: [{ type: "required", message: __("Volume selection is required") }], + }, + ], +}); + +export default createDetachSchema; diff --git a/app/javascript/packs/component-definitions-common.js b/app/javascript/packs/component-definitions-common.js index 164edaa3905..05fdf01f74d 100644 --- a/app/javascript/packs/component-definitions-common.js +++ b/app/javascript/packs/component-definitions-common.js @@ -11,6 +11,7 @@ import { Toolbar } from '../components/toolbar'; import ActionForm from '../components/action-form'; import AddRemoveHostAggregateForm from '../components/host-aggregate-form/add-remove-host-aggregate-form'; import AddRemoveSecurityGroupForm from '../components/vm-cloud-add-remove-security-group-form'; +import AddVolumeForm from '../components/vm-infra/add-volume'; import AeInlineMethod from '../components/AeInlineMethod'; import AggregateStatusCard from '../components/aggregate_status_card'; import AnsibleCredentialsForm from '../components/ansible-credentials-form'; @@ -116,6 +117,7 @@ import RefreshDataNotification from '../components/refresh-data-notification'; import RegionForm from '../components/region-form'; import RemoveCatalogItemModal from '../components/remove-catalog-item-modal'; import RemoveGenericItemModal from '../components/remove-generic-item-modal'; +import RemoveVolumeForm from '../components/vm-infra/remove-volume'; import ReportChartWidget from '../components/create-report-chart-form'; import ReportDataTable from '../components/data-tables/report-data-table/report-data-table'; import ReportList from '../components/data-tables/reports/ReportList'; @@ -190,6 +192,7 @@ import MiqAeClass from '../components/miq-ae-class'; ManageIQ.component.addReact('ActionForm', ActionForm); ManageIQ.component.addReact('AddRemoveHostAggregateForm', AddRemoveHostAggregateForm); ManageIQ.component.addReact('AddRemoveSecurityGroupForm', AddRemoveSecurityGroupForm); +ManageIQ.component.addReact('AddVolumeForm', AddVolumeForm); ManageIQ.component.addReact('AggregateStatusCard', AggregateStatusCard); ManageIQ.component.addReact('AeInlineMethod', AeInlineMethod); ManageIQ.component.addReact('AnsibleCredentialsForm', AnsibleCredentialsForm); @@ -300,6 +303,7 @@ ManageIQ.component.addReact('RefreshDataNotification', RefreshDataNotification); ManageIQ.component.addReact('RegionForm', RegionForm); ManageIQ.component.addReact('RemoveCatalogItemModal', RemoveCatalogItemModal); ManageIQ.component.addReact('RemoveGenericItemModal', RemoveGenericItemModal); +ManageIQ.component.addReact('RemoveVolumeForm', RemoveVolumeForm); ManageIQ.component.addReact('ReportChartWidget', ReportChartWidget); ManageIQ.component.addReact('ReportDataTable', ReportDataTable); ManageIQ.component.addReact('ReportList', ReportList); diff --git a/app/views/vm_common/_add_volume.html.haml b/app/views/vm_common/_add_volume.html.haml new file mode 100644 index 00000000000..5e2af925d9e --- /dev/null +++ b/app/views/vm_common/_add_volume.html.haml @@ -0,0 +1,6 @@ +#tab_div + = render :partial => "layouts/flash_msg" + %h3 + = _('Add Volume') + .col-md-12 + = react('AddVolumeForm', :recordId => @record.id.to_s, :redirect => url_for(:action => :show, :id => @record.id)) diff --git a/app/views/vm_common/_remove_volume.html.haml b/app/views/vm_common/_remove_volume.html.haml new file mode 100644 index 00000000000..d6a0fbb0269 --- /dev/null +++ b/app/views/vm_common/_remove_volume.html.haml @@ -0,0 +1,7 @@ +#tab_div + = render :partial => "layouts/flash_msg" + %h3= _('Detach Volume') + .col-md-12 + = react('RemoveVolumeForm', + :recordId => @record.id.to_s, + :redirect => url_for(:action => :show, :id => @record.id)) \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index ce1fd14bf9a..b62395107a1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3048,6 +3048,8 @@ retire show tagging_edit + persistentvolumeclaims + attached_volumes ] + compare_get, :post => %w[ @@ -3097,6 +3099,8 @@ wait_for_task win32_services ownership_update + add_volume + remove_volume ] + adv_search_post + compare_post + From 21542d2e46b0f9b1d4d73c68ecc0d88202700a5c Mon Sep 17 00:00:00 2001 From: chitra607 Date: Fri, 18 Jul 2025 04:21:12 +0000 Subject: [PATCH 2/5] updated --- app/controllers/vm_infra_controller.rb | 18 ++++++++---------- .../button/vm_attach_volume.rb | 2 ++ .../button/vm_detach_volume.rb | 2 ++ .../application_helper/toolbar/x_vm_center.rb | 4 ++-- app/views/vm_common/_add_volume.html.haml | 8 ++++++-- app/views/vm_common/_remove_volume.html.haml | 10 ++++++---- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/controllers/vm_infra_controller.rb b/app/controllers/vm_infra_controller.rb index 0aabd975a32..faddcfcf42f 100644 --- a/app/controllers/vm_infra_controller.rb +++ b/app/controllers/vm_infra_controller.rb @@ -21,30 +21,28 @@ def index def persistentvolumeclaims @record = find_record_with_rbac(VmOrTemplate, params[:id]) - pvcs = @record.persistentvolumeclaims(@record) render :json => { - :resources => pvcs, - :vm_name => @record.name, + :resources => pvcs, + :vm_name => @record.name, :vm_namespace => @record.location } rescue => e - render :json => { :error => e.message }, :status => :internal_server_error + render :json => {:error => e.message}, :status => 500 end def attached_volumes @record = find_record_with_rbac(VmOrTemplate, params[:id]) - attached = @record.attached_volumes(@record) - render json: { - resources: attached, - vm_name: @record.name, - vm_namespace: @record.location + render :json => { + :resources => attached, + :vm_name => @record.name, + :vm_namespace => @record.location } rescue => e - render :json => { :error => e.message }, :status => :internal_server_error + render :json => {:error => e.message}, :status => 500 end private diff --git a/app/helpers/application_helper/button/vm_attach_volume.rb b/app/helpers/application_helper/button/vm_attach_volume.rb index cf5fcef5e0b..67f3df59618 100644 --- a/app/helpers/application_helper/button/vm_attach_volume.rb +++ b/app/helpers/application_helper/button/vm_attach_volume.rb @@ -1,5 +1,7 @@ class ApplicationHelper::Button::VmAttachVolume < ApplicationHelper::Button::Basic needs :@record + + def visible? @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) end diff --git a/app/helpers/application_helper/button/vm_detach_volume.rb b/app/helpers/application_helper/button/vm_detach_volume.rb index 1a6af3dad55..d6ebe0c3059 100644 --- a/app/helpers/application_helper/button/vm_detach_volume.rb +++ b/app/helpers/application_helper/button/vm_detach_volume.rb @@ -1,5 +1,7 @@ class ApplicationHelper::Button::VmDetachVolume < ApplicationHelper::Button::Basic needs :@record + + def visible? @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) end diff --git a/app/helpers/application_helper/toolbar/x_vm_center.rb b/app/helpers/application_helper/toolbar/x_vm_center.rb index 0c1c7d48561..02876451a17 100644 --- a/app/helpers/application_helper/toolbar/x_vm_center.rb +++ b/app/helpers/application_helper/toolbar/x_vm_center.rb @@ -92,14 +92,14 @@ class ApplicationHelper::Toolbar::XVmCenter < ApplicationHelper::Toolbar::Basic 'fa fa-hdd-o fa-lg', t = N_('Attach Volume'), t, - :klass => ApplicationHelper::Button::VmAttachVolume + :klass => ApplicationHelper::Button::VmAttachVolume ), button( :instance_remove_volume, 'fa fa-trash-o fa-lg', t = N_('Detach Volume'), t, - :klass => ApplicationHelper::Button::VmDetachVolume + :klass => ApplicationHelper::Button::VmDetachVolume ), ] ), diff --git a/app/views/vm_common/_add_volume.html.haml b/app/views/vm_common/_add_volume.html.haml index 5e2af925d9e..f2ae242337a 100644 --- a/app/views/vm_common/_add_volume.html.haml +++ b/app/views/vm_common/_add_volume.html.haml @@ -1,6 +1,10 @@ -#tab_div +#tab-div = render :partial => "layouts/flash_msg" %h3 = _('Add Volume') .col-md-12 - = react('AddVolumeForm', :recordId => @record.id.to_s, :redirect => url_for(:action => :show, :id => @record.id)) + = react( + 'AddVolumeForm', + :recordId => record.id.to_s, + :redirect => url_for(:action => :show, :id => record.id) + ) diff --git a/app/views/vm_common/_remove_volume.html.haml b/app/views/vm_common/_remove_volume.html.haml index d6a0fbb0269..8754924314d 100644 --- a/app/views/vm_common/_remove_volume.html.haml +++ b/app/views/vm_common/_remove_volume.html.haml @@ -1,7 +1,9 @@ -#tab_div +#tab-div = render :partial => "layouts/flash_msg" %h3= _('Detach Volume') .col-md-12 - = react('RemoveVolumeForm', - :recordId => @record.id.to_s, - :redirect => url_for(:action => :show, :id => @record.id)) \ No newline at end of file + = react( + 'RemoveVolumeForm', + :recordId => record.id.to_s, + :redirect => url_for(:action => :show, :id => record.id) + ) From 53b4bc159c3838eeedc230fbf285d9710e916c12 Mon Sep 17 00:00:00 2001 From: chitra607 Date: Fri, 18 Jul 2025 04:34:25 +0000 Subject: [PATCH 3/5] updated --- app/controllers/vm_infra_controller.rb | 1 + .../application_helper/button/vm_attach_volume.rb | 9 ++++----- .../application_helper/button/vm_detach_volume.rb | 9 ++++----- app/views/vm_common/_add_volume.html.haml | 4 ++-- app/views/vm_common/_remove_volume.html.haml | 6 +++--- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/controllers/vm_infra_controller.rb b/app/controllers/vm_infra_controller.rb index faddcfcf42f..b282b786600 100644 --- a/app/controllers/vm_infra_controller.rb +++ b/app/controllers/vm_infra_controller.rb @@ -41,6 +41,7 @@ def attached_volumes :vm_name => @record.name, :vm_namespace => @record.location } + rescue => e render :json => {:error => e.message}, :status => 500 end diff --git a/app/helpers/application_helper/button/vm_attach_volume.rb b/app/helpers/application_helper/button/vm_attach_volume.rb index 67f3df59618..1fefd99d1a7 100644 --- a/app/helpers/application_helper/button/vm_attach_volume.rb +++ b/app/helpers/application_helper/button/vm_attach_volume.rb @@ -1,8 +1,7 @@ class ApplicationHelper::Button::VmAttachVolume < ApplicationHelper::Button::Basic - needs :@record - + needs :@record - def visible? - @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) - end + def visible? + @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) + end end \ No newline at end of file diff --git a/app/helpers/application_helper/button/vm_detach_volume.rb b/app/helpers/application_helper/button/vm_detach_volume.rb index d6ebe0c3059..c537cca5b95 100644 --- a/app/helpers/application_helper/button/vm_detach_volume.rb +++ b/app/helpers/application_helper/button/vm_detach_volume.rb @@ -1,8 +1,7 @@ class ApplicationHelper::Button::VmDetachVolume < ApplicationHelper::Button::Basic - needs :@record - + needs :@record - def visible? - @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) - end + def visible? + @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) + end end diff --git a/app/views/vm_common/_add_volume.html.haml b/app/views/vm_common/_add_volume.html.haml index f2ae242337a..c314ea83d72 100644 --- a/app/views/vm_common/_add_volume.html.haml +++ b/app/views/vm_common/_add_volume.html.haml @@ -5,6 +5,6 @@ .col-md-12 = react( 'AddVolumeForm', - :recordId => record.id.to_s, - :redirect => url_for(:action => :show, :id => record.id) + :recordId => @record.id.to_s, + :redirect => url_for(:action => :show, :id => @record.id) ) diff --git a/app/views/vm_common/_remove_volume.html.haml b/app/views/vm_common/_remove_volume.html.haml index 8754924314d..62ea6121a28 100644 --- a/app/views/vm_common/_remove_volume.html.haml +++ b/app/views/vm_common/_remove_volume.html.haml @@ -4,6 +4,6 @@ .col-md-12 = react( 'RemoveVolumeForm', - :recordId => record.id.to_s, - :redirect => url_for(:action => :show, :id => record.id) - ) + :recordId => @record.id.to_s, + :redirect => url_for(:action => :show, :id => @record.id) + ) \ No newline at end of file From e2cd265ae7b7a8dcbbdf4a84b2621287dc6b8d26 Mon Sep 17 00:00:00 2001 From: chitra607 Date: Fri, 18 Jul 2025 04:48:54 +0000 Subject: [PATCH 4/5] updated --- app/controllers/vm_infra_controller.rb | 6 +++--- app/helpers/application_helper/button/vm_attach_volume.rb | 3 +-- app/helpers/application_helper/button/vm_detach_volume.rb | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/controllers/vm_infra_controller.rb b/app/controllers/vm_infra_controller.rb index b282b786600..0e4482d0996 100644 --- a/app/controllers/vm_infra_controller.rb +++ b/app/controllers/vm_infra_controller.rb @@ -37,9 +37,9 @@ def attached_volumes attached = @record.attached_volumes(@record) render :json => { - :resources => attached, - :vm_name => @record.name, - :vm_namespace => @record.location + :resources => attached, + :vm_name => @record.name, + :vm_namespace => @record.location } rescue => e diff --git a/app/helpers/application_helper/button/vm_attach_volume.rb b/app/helpers/application_helper/button/vm_attach_volume.rb index 1fefd99d1a7..06dff7c69f6 100644 --- a/app/helpers/application_helper/button/vm_attach_volume.rb +++ b/app/helpers/application_helper/button/vm_attach_volume.rb @@ -1,6 +1,5 @@ class ApplicationHelper::Button::VmAttachVolume < ApplicationHelper::Button::Basic - needs :@record - + needs :@record def visible? @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) end diff --git a/app/helpers/application_helper/button/vm_detach_volume.rb b/app/helpers/application_helper/button/vm_detach_volume.rb index c537cca5b95..479d5e492d5 100644 --- a/app/helpers/application_helper/button/vm_detach_volume.rb +++ b/app/helpers/application_helper/button/vm_detach_volume.rb @@ -1,6 +1,5 @@ class ApplicationHelper::Button::VmDetachVolume < ApplicationHelper::Button::Basic - needs :@record - + needs :@record def visible? @record.kind_of?(ManageIQ::Providers::Kubevirt::InfraManager::Vm) end From d1f700db7df5fad2eb061b291d639f414aa686fb Mon Sep 17 00:00:00 2001 From: chitra607 Date: Fri, 18 Jul 2025 10:56:34 +0000 Subject: [PATCH 5/5] updated jsx --- app/javascript/components/vm-infra/add-volume.jsx | 3 ++- app/javascript/components/vm-infra/remove-volume.jsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/javascript/components/vm-infra/add-volume.jsx b/app/javascript/components/vm-infra/add-volume.jsx index 9dc251ec390..94b88c197c5 100644 --- a/app/javascript/components/vm-infra/add-volume.jsx +++ b/app/javascript/components/vm-infra/add-volume.jsx @@ -87,7 +87,8 @@ const AddVolumeForm = ({ recordId, redirect }) => { resource: { volume_name: values.newVolumeName.trim(), volume_size: values.newVolumeSize.trim(), - vm_id: recordId + vm_id: recordId, + device: values.device_mountpoint ? values.device_mountpoint : '' }, }; } diff --git a/app/javascript/components/vm-infra/remove-volume.jsx b/app/javascript/components/vm-infra/remove-volume.jsx index e6750338992..bbd2c70ea89 100644 --- a/app/javascript/components/vm-infra/remove-volume.jsx +++ b/app/javascript/components/vm-infra/remove-volume.jsx @@ -58,7 +58,8 @@ const DetachVolumeForm = ({ recordId, redirect }) => { action: "detach", resource: { volume_name: values.volumeName.trim(), - vm_id: recordId + vm_id: recordId, + device: values.device_mountpoint ? values.device_mountpoint : '' }, };