1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-20 14:03:36 +03:00

F #5529: Expose onevm nic-update (#2369)

This commit is contained in:
Frederick Borges 2022-11-23 19:06:37 +01:00 committed by GitHub
parent b2eb5555b1
commit 02fa0ae02f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 556 additions and 102 deletions

View File

@ -142,6 +142,7 @@ info-tabs:
actions:
attach_nic: true
detach_nic: true
update_nic: true
attach_secgroup: true
detach_secgroup: true

View File

@ -142,6 +142,7 @@ info-tabs:
actions:
attach_nic: true
detach_nic: true
update_nic: true
attach_secgroup: true
detach_secgroup: true

View File

@ -0,0 +1,58 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2022, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
// It uses the same schema and fields from AttachNic/QoS
import QOSOptions, {
STEP_ID as QOS_ID,
} from 'client/components/Forms/Vm/AttachNicForm/Steps/QOSOptions'
import { createSteps } from 'client/utils'
const Steps = createSteps([QOSOptions], {
transformInitialValue: (nic, schema) => {
const {
INBOUND_AVG_BW,
INBOUND_PEAK_BW,
INBOUND_PEAK_KB,
OUTBOUND_AVG_BW,
OUTBOUND_PEAK_BW,
OUTBOUND_PEAK_KB,
} = nic ?? {}
const castedValueQOS = schema.cast(
{
[QOS_ID]: {
INBOUND_AVG_BW,
INBOUND_PEAK_BW,
INBOUND_PEAK_KB,
OUTBOUND_AVG_BW,
OUTBOUND_PEAK_BW,
OUTBOUND_PEAK_KB,
},
},
{ stripUnknown: true }
)
return {
[QOS_ID]: castedValueQOS[QOS_ID],
}
},
transformBeforeSubmit: (formData) => {
const { [QOS_ID]: qos } = formData
return qos
},
})
export default Steps

View File

@ -0,0 +1,16 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2022, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
export { default } from 'client/components/Forms/Vm/UpdateNicForm/Steps'

View File

@ -38,6 +38,13 @@ const VolatileSteps = (configProps) =>
const AttachNicForm = (configProps) =>
AsyncLoadForm({ formPath: 'Vm/AttachNicForm' }, configProps)
/**
* @param {ConfigurationProps} configProps - Configuration
* @returns {ReactElement|CreateStepsCallback} Asynchronous loaded form
*/
const UpdateNicForm = (configProps) =>
AsyncLoadForm({ formPath: 'Vm/UpdateNicForm' }, configProps)
/**
* @param {ConfigurationProps} configProps - Configuration
* @returns {ReactElement|CreateStepsCallback} Asynchronous loaded form
@ -183,5 +190,6 @@ export {
SaveAsDiskForm,
SaveAsTemplateForm,
UpdateConfigurationForm,
UpdateNicForm,
VolatileSteps,
}

View File

@ -13,19 +13,25 @@
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import { memo } from 'react'
import { memo, useEffect } from 'react'
import PropTypes from 'prop-types'
import { Edit, Trash, ShieldAdd, ShieldCross } from 'iconoir-react'
import {
useAttachNicMutation,
useDetachNicMutation,
useUpdateNicMutation,
useAttachSecurityGroupMutation,
useDetachSecurityGroupMutation,
} from 'client/features/OneApi/vm'
import ButtonToTriggerForm from 'client/components/Forms/ButtonToTriggerForm'
import { AttachNicForm, AttachSecGroupForm } from 'client/components/Forms/Vm'
import {
AttachNicForm,
AttachSecGroupForm,
UpdateNicForm,
} from 'client/components/Forms/Vm'
import { useGeneralApi } from 'client/features/General'
import { jsonToXml } from 'client/models/Helper'
import { Tr, Translate } from 'client/components/HOC'
import { T } from 'client/constants'
@ -118,6 +124,48 @@ const DetachAction = memo(({ vmId, nic, onSubmit, sx }) => {
)
})
const UpdateAction = memo(({ vmId, nic, sx }) => {
const { enqueueSuccess } = useGeneralApi()
const [updateNic, { isSuccess }] = useUpdateNicMutation()
const { NIC_ID } = nic
const handleUpdate = async (formData) => {
const data = { NIC: formData }
const template = jsonToXml(data)
await updateNic({
id: vmId,
nic: NIC_ID,
template,
})
}
const updatedNicMessage = `${Tr(T.UpdatedNic)} - ${Tr(T.ID)} : ${NIC_ID}`
useEffect(() => isSuccess && enqueueSuccess(updatedNicMessage), [isSuccess])
return (
<ButtonToTriggerForm
buttonProps={{
'data-cy': `update-nic-${NIC_ID}`,
icon: <Edit />,
tooltip: Tr(T.Update),
sx,
}}
options={[
{
dialogProps: { title: T.Update, dataCy: 'modal-update-nic' },
form: () =>
UpdateNicForm({
stepProps: { defaultData: nic },
initialValues: nic,
}),
onSubmit: handleUpdate,
},
]}
/>
)
})
const AttachSecGroupAction = memo(({ vmId, nic, onSubmit, sx }) => {
const [attachSecGroup] = useAttachSecurityGroupMutation()
const { NIC_ID } = nic
@ -204,6 +252,8 @@ AttachAction.propTypes = ActionPropTypes
AttachAction.displayName = 'AttachActionButton'
DetachAction.propTypes = ActionPropTypes
DetachAction.displayName = 'DetachActionButton'
UpdateAction.propTypes = ActionPropTypes
UpdateAction.displayName = 'UpdateActionButton'
AttachSecGroupAction.propTypes = ActionPropTypes
AttachSecGroupAction.displayName = 'AttachSecGroupButton'
DetachSecGroupAction.propTypes = ActionPropTypes
@ -212,6 +262,7 @@ DetachSecGroupAction.displayName = 'DetachSecGroupButton'
export {
AttachAction,
DetachAction,
UpdateAction,
AttachSecGroupAction,
DetachSecGroupAction,
}

View File

@ -22,6 +22,7 @@ import NicCard from 'client/components/Cards/NicCard'
import {
AttachAction,
DetachAction,
UpdateAction,
AttachSecGroupAction,
DetachSecGroupAction,
} from 'client/components/Tabs/Vm/Network/Actions'
@ -34,8 +35,13 @@ import {
import { getActionsAvailable } from 'client/models/Helper'
import { VM_ACTIONS } from 'client/constants'
const { ATTACH_NIC, DETACH_NIC, ATTACH_SEC_GROUP, DETACH_SEC_GROUP } =
VM_ACTIONS
const {
ATTACH_NIC,
DETACH_NIC,
UPDATE_NIC,
ATTACH_SEC_GROUP,
DETACH_SEC_GROUP,
} = VM_ACTIONS
/**
* Renders the list of networks from a VM.
@ -83,6 +89,9 @@ const VmNetworkTab = ({ tabProps: { actions } = {}, id }) => {
{actionsAvailable.includes(DETACH_NIC) && (
<DetachAction nic={nic} vmId={id} />
)}
{actionsAvailable.includes(UPDATE_NIC) && (
<UpdateAction nic={nic} vmId={id} />
)}
{actionsAvailable.includes(ATTACH_SEC_GROUP) && (
<AttachSecGroupAction nic={nic} vmId={id} />
)}

View File

@ -283,6 +283,7 @@ module.exports = {
Empty: 'Empty',
NoDataAvailable: 'There is no data available',
ErrorsOcurred: '%s error(s) occurred',
UpdatedNic: 'Updated nic',
/* steps form */
AdvancedOptions: 'Advanced options',

View File

@ -784,6 +784,7 @@ export const VM_ACTIONS = {
// NETWORK
ATTACH_NIC: 'attach_nic',
DETACH_NIC: 'detach_nic',
UPDATE_NIC: 'update_nic',
ATTACH_SEC_GROUP: 'attach_secgroup',
DETACH_SEC_GROUP: 'detach_secgroup',
@ -1029,6 +1030,18 @@ export const DUMMY_VM_ACTIONS_BY_STATE = {
// NETWORK
[VM_ACTIONS.ATTACH_NIC]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DETACH_NIC]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.UPDATE_NIC]: [
STATES.INIT,
STATES.PENDING,
STATES.HOLD,
STATES.STOPPED,
STATES.SUSPENDED,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.CLONING,
STATES.CLONING_FAILURE,
STATES.RUNNING,
],
[VM_ACTIONS.ATTACH_SEC_GROUP]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DETACH_SEC_GROUP]: [STATES.POWEROFF, STATES.RUNNING],
@ -1211,6 +1224,18 @@ export const KVM_VM_ACTIONS_BY_STATE = {
// NETWORK
[VM_ACTIONS.ATTACH_NIC]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DETACH_NIC]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.UPDATE_NIC]: [
STATES.INIT,
STATES.PENDING,
STATES.HOLD,
STATES.STOPPED,
STATES.SUSPENDED,
STATES.POWEROFF,
STATES.UNDEPLOYED,
STATES.CLONING,
STATES.CLONING_FAILURE,
STATES.RUNNING,
],
[VM_ACTIONS.ATTACH_SEC_GROUP]: [STATES.POWEROFF, STATES.RUNNING],
[VM_ACTIONS.DETACH_SEC_GROUP]: [STATES.POWEROFF, STATES.RUNNING],

View File

@ -560,6 +560,26 @@ const vmApi = oneApi.injectEndpoints({
},
invalidatesTags: (_, __, { id }) => [{ type: VM, id }],
}),
updateNic: builder.mutation({
/**
* Updates a network interface from a virtual machine.
*
* @param {object} params - Request parameters
* @param {string} params.id - Virtual machine id
* @param {string} params.nic - NIC id
* @param {number} params.append - Append
* @param {string} params.template - NIC id
* @returns {number} Virtual machine id
* @throws Fails when response isn't code 200
*/
query: (params) => {
const name = Actions.VM_NIC_UPDATE
const command = { name, ...Commands[name] }
return { params, command }
},
invalidatesTags: (_, __, { id }) => [{ type: VM, id }],
}),
attachSecurityGroup: builder.mutation({
/**
* Attaches a security group to a network interface of a VM,
@ -1071,6 +1091,7 @@ export const {
useResizeDiskMutation,
useAttachNicMutation,
useDetachNicMutation,
useUpdateNicMutation,
useAttachSecurityGroupMutation,
useDetachSecurityGroupMutation,
useChangeVmPermissionsMutation,

View File

@ -47,6 +47,7 @@ const VM_DISK_DETACH = 'vm.detach'
const VM_DISK_RESIZE = 'vm.diskresize'
const VM_NIC_ATTACH = 'vm.attachnic'
const VM_NIC_DETACH = 'vm.detachnic'
const VM_NIC_UPDATE = 'vm.updatenic'
const VM_SEC_GROUP_ATTACH = 'vm.attachsg'
const VM_SEC_GROUP_DETACH = 'vm.detachsg'
const VM_SCHED_ADD = 'vm.schedadd'
@ -89,6 +90,7 @@ const Actions = {
VM_DISK_RESIZE,
VM_NIC_ATTACH,
VM_NIC_DETACH,
VM_NIC_UPDATE,
VM_SEC_GROUP_ATTACH,
VM_SEC_GROUP_DETACH,
VM_SCHED_ADD,
@ -362,6 +364,28 @@ module.exports = {
},
},
},
[VM_NIC_UPDATE]: {
// inspected
httpMethod: PUT,
params: {
id: {
from: resource,
default: 0,
},
nic: {
from: postBody,
default: 0,
},
template: {
from: postBody,
default: '',
},
append: {
from: postBody,
default: 0,
},
},
},
[VM_SEC_GROUP_ATTACH]: {
// inspected
httpMethod: PUT,

View File

@ -418,6 +418,7 @@ tabs:
VM.disk_saveas: true
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -91,6 +91,7 @@ tabs:
VM.disk_saveas: true
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -414,6 +414,7 @@ tabs:
VM.disk_resize: false
VM.attachnic: false
VM.detachnic: false
VM.updatenic: false
VM.snapshot_create: false
VM.snapshot_revert: false
VM.snapshot_delete: false

View File

@ -410,6 +410,7 @@ tabs:
VM.disk_resize: false
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -418,6 +418,7 @@ tabs:
VM.disk_saveas: true
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -91,6 +91,7 @@ tabs:
VM.disk_saveas: true
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -417,6 +417,7 @@ tabs:
VM.disk_resize: false
VM.attachnic: false
VM.detachnic: false
VM.updatenic: false
VM.snapshot_create: false
VM.snapshot_revert: false
VM.snapshot_delete: false

View File

@ -410,6 +410,7 @@ tabs:
VM.disk_resize: false
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -416,6 +416,7 @@ tabs:
VM.disk_resize: true
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -92,6 +92,7 @@ tabs:
VM.disk_saveas: true
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -417,6 +417,7 @@ tabs:
VM.disk_resize: false
VM.attachnic: false
VM.detachnic: false
VM.updatenic: false
VM.snapshot_create: false
VM.snapshot_revert: false
VM.snapshot_delete: false

View File

@ -410,6 +410,7 @@ tabs:
VM.disk_resize: false
VM.attachnic: true
VM.detachnic: true
VM.updatenic: true
VM.snapshot_create: true
VM.snapshot_revert: true
VM.snapshot_delete: true

View File

@ -102,6 +102,8 @@ module OpenNebulaJSON
nic_attach(action_hash['params'])
when 'detachnic'
nic_detach(action_hash['params'])
when 'updatenic'
nic_update(action_hash['params'])
when 'update'
update(action_hash['params'])
when 'updateconf'
@ -246,6 +248,12 @@ module OpenNebulaJSON
super(params['nic_id'].to_i)
end
def nic_update(params = {})
template_json = params['nic_template']
template = template_to_str(template_json)
super(params['nic_id'].to_i, template)
end
def update(params = {})
if !params['append'].nil?
super(params['template_raw'], params['append'])

View File

@ -722,6 +722,10 @@ define(function(require) {
var action_obj = {"nic_id": params.data.extra_param};
OpenNebulaAction.simple_action(params, RESOURCE, "detachnic", action_obj);
},
"updatenic" : function(params) {
var action_obj = params.data.extra_param
OpenNebulaAction.simple_action(params, RESOURCE, "updatenic", action_obj);
},
"rename" : function(params) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "rename", action_obj);

View File

@ -34,6 +34,7 @@ define(function(require) {
*/
var TemplateHTML = require('hbs!./nic-tab/html');
var QoSHTML = require('hbs!./nic-tab/QoS/html');
/*
CONSTANTS
@ -94,7 +95,8 @@ define(function(require) {
'nicTabId': this.nicTabId,
'vnetsTableSelectHTML': this.vnetsTable.dataTableHTML,
'vnetsTableAutoSelectHTML': this.vnetsTableAuto.dataTableHTML,
'secgroupsTableSelectHTML': this.secgroupsTable.dataTableHTML
'secgroupsTableSelectHTML': this.secgroupsTable.dataTableHTML,
'QoSFields': QoSHTML()
});
}

View File

@ -0,0 +1,46 @@
<fieldset class="not_firecracker">
<legend>{{tr "Override Network Inbound Traffic QoS"}}</legend>
<div class="row">
<div class="medium-4 columns">
<label>
{{tr "Average bandwidth (KBytes/s)"}}
<input type="number" wizard_field="INBOUND_AVG_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak bandwidth (KBytes/s)"}}
<input type="number" wizard_field="INBOUND_PEAK_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak burst (KBytes)"}}
<input type="number" wizard_field="INBOUND_PEAK_KB"/>
</label>
</div>
</div>
</fieldset>
<fieldset class="not_firecracker">
<legend>{{tr "Override Network Outbound Traffic QoS"}}</legend>
<div class="row">
<div class="medium-4 columns">
<label>
{{tr "Average bandwidth (KBytes/s)"}}
<input type="number" wizard_field="OUTBOUND_AVG_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak bandwidth (KBytes/s)"}}
<input type="number" wizard_field="OUTBOUND_PEAK_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak burst (KBytes)"}}
<input type="number" wizard_field="OUTBOUND_PEAK_KB"/>
</label>
</div>
</div>
</fieldset>

View File

@ -274,52 +274,7 @@
</div>
</div>
</fieldset>
<fieldset class="not_firecracker">
<legend>{{tr "Override Network Inbound Traffic QoS"}}</legend>
<div class="row">
<div class="medium-4 columns">
<label>
{{tr "Average bandwidth (KBytes/s)"}}
<input type="number" wizard_field="INBOUND_AVG_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak bandwidth (KBytes/s)"}}
<input type="number" wizard_field="INBOUND_PEAK_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak burst (KBytes)"}}
<input type="number" wizard_field="INBOUND_PEAK_KB"/>
</label>
</div>
</div>
</fieldset>
<fieldset class="not_firecracker">
<legend>{{tr "Override Network Outbound Traffic QoS"}}</legend>
<div class="row">
<div class="medium-4 columns">
<label>
{{tr "Average bandwidth (KBytes/s)"}}
<input type="number" wizard_field="OUTBOUND_AVG_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak bandwidth (KBytes/s)"}}
<input type="number" wizard_field="OUTBOUND_PEAK_BW"/>
</label>
</div>
<div class="medium-4 columns">
<label>
{{tr "Peak burst (KBytes)"}}
<input type="number" wizard_field="OUTBOUND_PEAK_KB"/>
</label>
</div>
</div>
</fieldset>
{{{QoSFields}}}
<fieldset class="not_firecracker">
<legend>{{tr "Hardware"}}</legend>
<div class="row">

View File

@ -36,7 +36,8 @@ define(function(require) {
require("./vms-tab/dialogs/snapshot"),
require("./vms-tab/dialogs/revert"),
require("./vms-tab/dialogs/saveas-template"),
require("./vms-tab/dialogs/backup")
require("./vms-tab/dialogs/backup"),
require("./vms-tab/dialogs/update-nic")
];
var _panelsHooks = [

View File

@ -107,6 +107,7 @@ define(function(require) {
"VM.detachdisk": _commonActions.singleAction("detachdisk"),
"VM.attachnic": _commonActions.singleAction("attachnic"),
"VM.detachnic": _commonActions.singleAction("detachnic"),
"VM.updatenic": _commonActions.singleAction("updatenic"),
"VM.resize": _commonActions.singleAction("resize"),
"VM.disk_resize": _commonActions.singleAction("disk_resize"),
"VM.snapshot_create": _commonActions.singleAction("snapshot_create"),

View File

@ -0,0 +1,126 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2022, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
define(function(require) {
/*
DEPENDENCIES
*/
var OpennebulaVM = require("opennebula/vm");
var BaseDialog = require("utils/dialogs/dialog");
var Sunstone = require("sunstone");
var Notifier = require("utils/notifier");
var Tips = require("utils/tips");
var NicTab = require("tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab");
var WizardFields = require("utils/wizard-fields");
/*
TEMPLATES
*/
var QoSHTML = require('hbs!tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab/QoS/html');
var TemplateHTML = require("hbs!./update-nic/html");
/*
CONSTANTS
*/
var DIALOG_ID = require("./update-nic/dialogId");
var TAB_ID = require("../tabId");
/*
CONSTRUCTOR
*/
function Dialog() {
this.dialogId = DIALOG_ID;
this.nicTab = new NicTab(DIALOG_ID + "NicTab");
BaseDialog.call(this);
};
Dialog.DIALOG_ID = DIALOG_ID;
Dialog.prototype = Object.create(BaseDialog.prototype);
Dialog.prototype.constructor = Dialog;
Dialog.prototype.html = _html;
Dialog.prototype.onShow = _onShow;
Dialog.prototype.setup = _setup;
Dialog.prototype.setElement = _setElement;
Dialog.prototype.setNicId = _setNicId;
return Dialog;
/*
FUNCTION DEFINITIONS
*/
function _html() {
return TemplateHTML({
"dialogId": this.dialogId,
"QoSFields": QoSHTML()
});
}
function _setup(context) {
this.context = context;
var that = this;
Tips.setup(context);
$("#parent", context).hide();
$("#" + DIALOG_ID + "Form", context).submit(function() {
var obj = {
nic_id: that.nicId,
nic_template: { NIC: WizardFields.retrieve(context) }
}
Sunstone.runAction("VM.updatenic", that.element.ID, obj);
Sunstone.getDialog(DIALOG_ID).hide();
Sunstone.getDialog(DIALOG_ID).reset();
return false;
});
return false;
}
function _onShow(context) {
var that = this;
this.setNames( {tabId: TAB_ID} );
var nics = Array.isArray(this.element.TEMPLATE.NIC) ? this.element.TEMPLATE.NIC : [this.element.TEMPLATE.NIC]
var nicToUpdate = nics.filter(function(nic) {
return nic.NIC_ID === that.nicId
})[0]
WizardFields.fill(context, $.extend({}, nicToUpdate))
return false;
}
function _setElement(element) {
this.element = element;
}
function _setNicId(nicId) {
this.nicId = nicId
}
});

View File

@ -0,0 +1,19 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2022, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
define(function(require) {
return 'updateNICVMDialog';
});

View File

@ -0,0 +1,37 @@
{{! -------------------------------------------------------------------------- }}
{{! Copyright 2002-2022, OpenNebula Project, OpenNebula Systems }}
{{! }}
{{! Licensed under the Apache License, Version 2.0 (the "License"); you may }}
{{! not use this file except in compliance with the License. You may obtain }}
{{! a copy of the License at }}
{{! }}
{{! http://www.apache.org/licenses/LICENSE-2.0 }}
{{! }}
{{! Unless required by applicable law or agreed to in writing, software }}
{{! distributed under the License is distributed on an "AS IS" BASIS, }}
{{! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }}
{{! See the License for the specific language governing permissions and }}
{{! limitations under the License. }}
{{! -------------------------------------------------------------------------- }}
<div id="{{dialogId}}" class="reveal large" data-reveal>
<div class="row">
<div class="large-12 columns">
<h3 class="subheader" id="">{{tr "Update nic"}}</h3>
</div>
</div>
<div class="confirm-resources-header"></div>
<div class="reveal-body">
<form id="{{dialogId}}Form" action="">
{{{QoSFields}}}
<div class="reveal-footer">
<div class="form_buttons">
<button class="button radius right success" id="update_nic_button" type="submit" value="VM.updatenic">{{tr "Update"}}</button>
</div>
</div>
<button class="close-button" data-close aria-label="{{tr "Close modal"}}" type="button">
<span aria-hidden="true">&times;</span>
</button>
</form>
</div>
</div>

View File

@ -46,6 +46,7 @@ define(function(require) {
var TAB_ID = require("../tabId");
var PANEL_ID = require("./network/panelId");
var ATTACH_NIC_DIALOG_ID = require("../dialogs/attach-nic/dialogId");
var UPDATE_NIC_DIALOG_ID = require("../dialogs/update-nic/dialogId");
var ATTACH_SG_DIALOG_ID = require("../dialogs/attach-sg/dialogId");
var CONFIRM_DIALOG_ID = require("utils/dialogs/generic-confirm/dialogId");
var XML_ROOT = "VM";
@ -259,6 +260,60 @@ define(function(require) {
return ips.length === 0 ? defaultValue : ips.join('<br/>');
}
function getNicActions(context, is_alias = false, is_pci = false){
var actions = "";
if (
context.element.STATE == OpenNebulaVM.STATES.ACTIVE && (
context.element.LCM_STATE == OpenNebulaVM.LCM_STATES.HOTPLUG_NIC ||
context.element.LCM_STATE == OpenNebulaVM.LCM_STATES.HOTPLUG_NIC_POWEROFF
)
) {
actions = Locale.tr("attach/detach in progress");
} else {
if(Config.isTabActionEnabled("vms-tab", "VM.detachnic")){
var icon = $("<i/>",{class:"fas fa-times"});
var anchorAttributes = {class: "detachnic", href: "VM.detachnic"};
var anchor = $("<a/>",anchorAttributes).append(icon);
actions += (validateAction(context,"VM.detachnic"))
? (isFirecracker(context)
? (isPowerOff(context) ? anchor.get(0).outerHTML : "")
: anchor.get(0).outerHTML
)
: "";
}
if (!is_pci && !is_alias){
if (Config.isTabActionEnabled("vms-tab", "VM.updatenic")){
var icon = $("<i/>",{class:"fas fa-edit"});
var anchorAttributes = {class: "updatenic", style: "padding-left: 1em"};
var anchor = $("<a/>",anchorAttributes).append(icon);
actions += (validateAction(context,"VM.updatenic"))
? (isFirecracker(context)
? (isPowerOff(context) ? anchor.get(0).outerHTML : "")
: anchor.get(0).outerHTML
)
: "";
}
if(Config.isTabActionEnabled("vms-tab", "VM.attachsg")){
var icon = $("<i/>",{class:"fas fa-shield-alt"});
var anchorAttributes = {class: "attachsg", style: "padding-left: 1em"};
var tip = "<span class=\"tip\">" + Locale.tr("Attach security group") + "</span>"
var anchor = $("<a/>",anchorAttributes).append(icon);
actions += (validateAction(context,"VM.attachsg"))
? (isFirecracker(context)
? (isPowerOff(context) ? anchor.get(0).outerHTML : "")
: anchor.get(0).outerHTML
)
: "";
}
}
}
return actions
}
function _setup(context) {
var that = this;
@ -312,46 +367,6 @@ define(function(require) {
var is_pci = (nic.PCI_ID != undefined);
var actions = "";
// Attach / Detach
if (
that.element.STATE == OpenNebulaVM.STATES.ACTIVE && (
that.element.LCM_STATE == OpenNebulaVM.LCM_STATES.HOTPLUG_NIC ||
that.element.LCM_STATE == OpenNebulaVM.LCM_STATES.HOTPLUG_NIC_POWEROFF
)
) {
actions = Locale.tr("attach/detach in progress");
} else {
if(Config.isTabActionEnabled("vms-tab", "VM.detachnic")){
var icon = $("<i/>",{class:"fas fa-times"});
var anchorAttributes = {class: "detachnic", href: "VM.detachnic"};
var anchor = $("<a/>",anchorAttributes).append(icon); //"<a href=\"VM.detachnic\" class=\"detachnic\" ><i class=\"fas fa-times\"/></a>";
actions += (validateAction(that,"VM.detachnic"))
? (isFirecracker(that)
? (isPowerOff(that) ? anchor.get(0).outerHTML : "")
: anchor.get(0).outerHTML
)
: "";
}
if (!is_pci){
if(Config.isTabActionEnabled("vms-tab", "VM.attachsg")){
var icon = $("<i/>",{class:"fas fa-shield-alt"});
var anchorAttributes = {class: "attachsg", style: "padding-left: 1em"};
var tip = "<span class=\"tip\">" + Locale.tr("Attach security group") + "</span>"
var anchor = $("<a/>",anchorAttributes).append(icon);
actions += (validateAction(that,"VM.attachsg"))
? (isFirecracker(that)
? (isPowerOff(that) ? anchor.get(0).outerHTML : "")
: anchor.get(0).outerHTML
)
: "";
}
}
}
var secgroups = [];
var nic_secgroups = {};
@ -391,7 +406,7 @@ define(function(require) {
for(var j = 0; j < alias.length; j++) {
if (alias_ids.length > 0 && alias_ids.includes(alias[j].NIC_ID)) {
alias[j].ACTIONS = actions;
alias[j].ACTIONS = getNicActions(that, true, is_pci);
nic_alias.push(alias[j]);
}
@ -405,7 +420,7 @@ define(function(require) {
PCI_ADDRESS: pci_address,
IP6_ULA : _ipTr(nic, "IP6_ULA"),
IP6_GLOBAL : _ipTr(nic, "IP6_GLOBAL"),
ACTIONS : actions,
ACTIONS : getNicActions(that, false, is_pci),
SECURITY_GROUP_RULES : secgroups
});
}
@ -593,6 +608,19 @@ define(function(require) {
});
}
if (Config.isTabActionEnabled("vms-tab", "VM.updatenic")) {
context.off("click", ".updatenic");
context.on("click", ".updatenic", function() {
var nic_id = $(this).parents("tr").attr("nic_id");
var dialog = Sunstone.getDialog(UPDATE_NIC_DIALOG_ID);
dialog.reset();
dialog.setElement(that.element);
dialog.setNicId(nic_id);
dialog.show();
return false;
});
}
if (Config.isTabActionEnabled("vms-tab", "VM.attachsg")){
context.off("click", ".attachsg");
context.on("click", ".attachsg", function() {
@ -663,8 +691,8 @@ define(function(require) {
Sunstone.runAction("VM.attachsg", element_id, nic_id);
Sunstone.getDialog(CONFIRM_DIALOG_ID).reset();
Sunstone.getDialog(CONFIRM_DIALOG_ID).show();
Sunstone.getDialog(ATTACH_SG_DIALOG_ID).reset();
Sunstone.getDialog(ATTACH_SG_DIALOG_ID).show();
return false;
}

View File

@ -23,16 +23,16 @@ define(function(require) {
["VM.resize", "VM.terminate_hard", "VM.recover"];
STATE_ACTIONS[OpenNebulaVM.STATES.PENDING] =
["VM.hold", "VM.deploy", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.resize"];
["VM.hold", "VM.deploy", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.resize", "VM.updatenic"];
STATE_ACTIONS[OpenNebulaVM.STATES.HOLD] =
["VM.release", "VM.deploy", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.resize"];
["VM.release", "VM.deploy", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.resize", "VM.updatenic"];
STATE_ACTIONS[OpenNebulaVM.STATES.ACTIVE] =
["VM.recover","VM.updateconf","VM.resize"];
STATE_ACTIONS[OpenNebulaVM.STATES.STOPPED] =
["VM.resume", "VM.deploy", "VM.terminate_hard", "VM.recover"];
["VM.resume", "VM.deploy", "VM.terminate_hard", "VM.recover", "VM.updatenic"];
STATE_ACTIONS[OpenNebulaVM.STATES.SUSPENDED] =
["VM.resume", "VM.disk_saveas", "VM.disk_snapshot_create", "VM.disk_snapshot_revert", "VM.disk_snapshot_delete", "VM.stop", "VM.terminate_hard", "VM.recover", "VM.migrate"];
@ -44,10 +44,10 @@ define(function(require) {
[];
STATE_ACTIONS[OpenNebulaVM.STATES.POWEROFF] =
["VM.resched", "VM.resume", "VM.resize", "VM.attachdisk", "VM.detachdisk", "VM.attachnic", "VM.detachnic", "VM.disk_saveas", "VM.disk_snapshot_create", "VM.disk_snapshot_revert", "VM.disk_snapshot_delete", "VM.migrate", "VM.undeploy", "VM.undeploy_hard", "VM.save_as_template", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.disk_resize", "VM.snapshot_delete", "VM.upload_marketplace_dialog", "VM.attachsg", "VM.detachsg", "VM.backup_dialog"];
["VM.resched", "VM.resume", "VM.resize", "VM.attachdisk", "VM.detachdisk", "VM.attachnic", "VM.detachnic", "VM.updatenic", "VM.disk_saveas", "VM.disk_snapshot_create", "VM.disk_snapshot_revert", "VM.disk_snapshot_delete", "VM.migrate", "VM.undeploy", "VM.undeploy_hard", "VM.save_as_template", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.disk_resize", "VM.snapshot_delete", "VM.upload_marketplace_dialog", "VM.attachsg", "VM.detachsg", "VM.backup_dialog"];
STATE_ACTIONS[OpenNebulaVM.STATES.UNDEPLOYED] =
["VM.resume", "VM.resize", "VM.deploy", "VM.updateconf", "VM.terminate_hard", "VM.recover"];
["VM.resume", "VM.resize", "VM.deploy", "VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.updatenic"];
STATE_ACTIONS[OpenNebulaVM.STATES.CLONING] =
["VM.updateconf", "VM.terminate_hard", "VM.recover", "VM.resize"];
@ -60,7 +60,7 @@ define(function(require) {
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.PROLOG ] = ["VM.updateconf"];
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.BOOT ] = [];
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.RUNNING ] =
["VM.stop", "VM.suspend", "VM.reboot", "VM.reboot_hard", "VM.resched", "VM.unresched", "VM.poweroff", "VM.poweroff_hard", "VM.undeploy", "VM.undeploy_hard", "VM.migrate", "VM.migrate_live", "VM.migrate_poff", "VM.migrate_poff_hard", "VM.attachdisk", "VM.detachdisk", "VM.attachnic", "VM.detachnic", "VM.disk_saveas", "VM.disk_snapshot_create", "VM.disk_snapshot_delete", "VM.terminate", "VM.terminate_hard", "VM.disk_resize", "VM.attachsg", "VM.detachsg", "VM.backup_dialog"];
["VM.stop", "VM.suspend", "VM.reboot", "VM.reboot_hard", "VM.resched", "VM.unresched", "VM.poweroff", "VM.poweroff_hard", "VM.undeploy", "VM.undeploy_hard", "VM.migrate", "VM.migrate_live", "VM.migrate_poff", "VM.migrate_poff_hard", "VM.attachdisk", "VM.detachdisk", "VM.attachnic", "VM.detachnic", "VM.updatenic", "VM.disk_saveas", "VM.disk_snapshot_create", "VM.disk_snapshot_delete", "VM.terminate", "VM.terminate_hard", "VM.disk_resize", "VM.attachsg", "VM.detachsg", "VM.backup_dialog"];
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.MIGRATE ] = [];
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.SAVE_STOP ] = [];
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.SAVE_SUSPEND ] = [];