diff --git a/debian/cloudstack-agent.install b/debian/cloudstack-agent.install index a3cc86964dd..d708514fd14 100644 --- a/debian/cloudstack-agent.install +++ b/debian/cloudstack-agent.install @@ -21,6 +21,7 @@ /etc/init.d/cloudstack-agent /usr/bin/cloudstack-setup-agent /usr/bin/cloudstack-ssh +/usr/bin/cloudstack-agent-upgrade /var/log/cloudstack/agent /usr/share/cloudstack-agent/lib/* /usr/share/cloudstack-agent/plugins diff --git a/debian/rules b/debian/rules index 49ad526f696..8cae7f3d208 100755 --- a/debian/rules +++ b/debian/rules @@ -71,7 +71,7 @@ install: install -D packaging/debian/init/cloud-agent $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-agent install -D agent/target/transformed/cloud-setup-agent $(DESTDIR)/usr/bin/cloudstack-setup-agent install -D agent/target/transformed/cloud-ssh $(DESTDIR)/usr/bin/cloudstack-ssh - install -D agent/target/transformed/cloudstack-agent-upgrade $(DESTDIR)/usr/bin/cloudstack-setup-agent + install -D agent/target/transformed/cloudstack-agent-upgrade $(DESTDIR)/usr/bin/cloudstack-agent-upgrade install -D agent/target/transformed/libvirtqemuhook $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/ install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java index c1cbdc772cc..9f0f5311a28 100644 --- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java @@ -41,6 +41,9 @@ public class DataMotionServiceImpl implements DataMotionService { @Override public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { + if (srcData.getDataStore() == null || destData.getDataStore() == null) { + throw new CloudRuntimeException("can't find data store"); + } if (srcData.getDataStore().getDriver().canCopy(srcData, destData)) { srcData.getDataStore().getDriver().copyAsync(srcData, destData, callback); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index 2649452611f..211f6685c57 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -575,12 +575,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw s_logger.info("Worker VM's owner management server has changed runid, recycle it"); return true; } - + + // disable time-out check until we have found out a VMware API that can check if + // there are pending tasks on the subject VM +/* if(System.currentTimeMillis() - startTick > _hungWorkerTimeout) { if(s_logger.isInfoEnabled()) s_logger.info("Worker VM expired, seconds elapsed: " + (System.currentTimeMillis() - startTick) / 1000); return true; } +*/ return false; } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java index ed607e118d2..3079998198c 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java @@ -80,8 +80,15 @@ public class VmwareContextFactory { public static VmwareContext getContext(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception { VmwareContext context = s_pool.getContext(vCenterAddress, vCenterUserName); - if(context == null) + if(context == null) { context = create(vCenterAddress, vCenterUserName, vCenterPassword); + } else { + if(!context.validate()) { + s_logger.info("Validation of the context faild. dispose and create a new one"); + context.close(); + context = create(vCenterAddress, vCenterUserName, vCenterPassword); + } + } if(context != null) { context.registerStockObject(VmwareManager.CONTEXT_STOCK_NAME, s_vmwareMgr); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 2d404171b54..fd56cc194c8 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -1618,12 +1618,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa throw new Exception(msg); } +/* if(!isVMWareToolsInstalled(vmMo)){ String errMsg = "vmware tools is not installed or not running, cannot add nic to vm " + vmName; s_logger.debug(errMsg); return new PlugNicAnswer(cmd, false, "Unable to execute PlugNicCommand due to " + errMsg); } - +*/ // TODO need a way to specify the control of NIC device type VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.E1000; @@ -1698,12 +1699,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa throw new Exception(msg); } +/* if(!isVMWareToolsInstalled(vmMo)){ String errMsg = "vmware tools not installed or not running, cannot remove nic from vm " + vmName; s_logger.debug(errMsg); return new UnPlugNicAnswer(cmd, false, "Unable to execute unPlugNicCommand due to " + errMsg); } - +*/ VirtualDevice nic = findVirtualNicDevice(vmMo, cmd.getNic().getMac()); if ( nic == null ) { return new UnPlugNicAnswer(cmd, true, "success"); diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageContextFactory.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageContextFactory.java index 5365e58e78e..253d6fd3517 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageContextFactory.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageContextFactory.java @@ -16,11 +16,15 @@ // under the License. package com.cloud.storage.resource; +import org.apache.log4j.Logger; + import com.cloud.hypervisor.vmware.util.VmwareClient; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareContextPool; public class VmwareSecondaryStorageContextFactory { + private static final Logger s_logger = Logger.getLogger(VmwareSecondaryStorageContextFactory.class); + private static volatile int s_seq = 1; private static VmwareContextPool s_pool; @@ -51,6 +55,12 @@ public class VmwareSecondaryStorageContextFactory { VmwareContext context = s_pool.getContext(vCenterAddress, vCenterUserName); if(context == null) { context = create(vCenterAddress, vCenterUserName, vCenterPassword); + } else { + if(!context.validate()) { + s_logger.info("Validation of the context faild. dispose and create a new one"); + context.close(); + context = create(vCenterAddress, vCenterUserName, vCenterPassword); + } } if(context != null) { diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index 773c2c8374f..c86476e2957 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -553,6 +553,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService, throws ResourceUnavailableException { boolean handled = false; switch (purpose){ + /* StaticNatRule would be applied by Firewall provider, since the incompatible of two object */ + case StaticNat: case Firewall: for (FirewallServiceProvider fwElement: _firewallElements) { Network.Provider provider = fwElement.getProvider(); @@ -577,18 +579,6 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService, break; } break; - case StaticNat: - for (StaticNatServiceProvider element: _staticNatElements) { - Network.Provider provider = element.getProvider(); - boolean isSnatProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.StaticNat, provider); - if (!isSnatProvider) { - continue; - } - handled = element.applyStaticNats(network, (List) rules); - if (handled) - break; - } - break; /* case NetworkACL: for (NetworkACLServiceProvider element: _networkAclElements) { Network.Provider provider = element.getProvider(); diff --git a/ui/plugins/netapp b/ui/plugins/netapp new file mode 120000 index 00000000000..21f67e4ad49 --- /dev/null +++ b/ui/plugins/netapp @@ -0,0 +1 @@ +/Users/csuich/CloudStack/workspace/ui-plugin/ \ No newline at end of file diff --git a/ui/scripts/events.js b/ui/scripts/events.js index 46d45c04605..38f7136c140 100644 --- a/ui/scripts/events.js +++ b/ui/scripts/events.js @@ -111,6 +111,9 @@ data: data, success: function(data) { args.response.success(); + }, + error:function(data) { + args.response.error(parseXMLHttpResponse(data)); } }); } @@ -452,6 +455,9 @@ success: function(data) { args.response.success(); + }, + error:function(data) { + args.response.error(parseXMLHttpResponse(data)); } }); } diff --git a/ui/scripts/ui/widgets/dataTable.js b/ui/scripts/ui/widgets/dataTable.js index 66d70956a42..4c025314be0 100644 --- a/ui/scripts/ui/widgets/dataTable.js +++ b/ui/scripts/ui/widgets/dataTable.js @@ -83,12 +83,12 @@ .addClass('data-table') .appendTo($table.parent()) .append( - $table.remove() + $table.detach() ); $table = $mainContainer; var $theadContainer = $('
').addClass('fixed-header').prependTo($table); var $theadTable = $('').appendTo($theadContainer).attr('nowrap', 'nowrap'); - var $thead = $table.find('thead').remove().appendTo($theadTable); + var $thead = $table.find('thead').detach().appendTo($theadTable); return $thead; }; @@ -238,9 +238,9 @@ $table.find('tbody').closest('table').addClass('body'); } - $table.find('th').bind('mousemove mouseout', hoverResizableEvent); - $table.find('th').bind('mousedown mousemove mouseup mouseout', resizeDragEvent); - $table.find('th').bind('click', function(event) { + $table.find('th:not(:has(input))').bind('mousemove mouseout', hoverResizableEvent); + $table.find('th:not(:has(input))').bind('mousedown mousemove mouseup mouseout', resizeDragEvent); + $table.find('th:not(:has(input))').bind('click', function(event) { if ($(this).hasClass('resizable')) { return false; } diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 076b3ab5c4d..a47c490a935 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -27,16 +27,29 @@ var messages = args.action ? args.action.messages : {}; var preAction = args.action ? args.action.preAction : {}; var action = args.action ? args.action.action : {}; + var multiSelect = args.action.isMultiSelectAction; var needsRefresh = args.action.needsRefresh; var section; - var data = { - id: $instanceRow.data('list-view-item-id'), - jsonObj: $instanceRow.data('jsonObj') - }; + var data; + var messageArgs; + if (multiSelect) { + data = { + id: $.map($instanceRow, function(elem) { return $(elem).data('list-view-item-id'); }), + jsonObj: $.map($instanceRow, function(elem) { return $(elem).data('jsonObj'); }) + }; + messageArgs = { + name: $.map($instanceRow, function(elem) { return $(elem).find('td.name span').html() }) + }; + } else { + data = { + id: $instanceRow.data('list-view-item-id'), + jsonObj: $instanceRow.data('jsonObj') + }; + messageArgs = { + name: $instanceRow.find('td.name span').html() + }; + } var $listView = $instanceRow.closest('.list-view'); - var messageArgs = { - name: $instanceRow.find('td.name span').html() - }; if (args.data) $.extend(true, data, args.data); if (listViewArgs) section = listViewArgs.section; @@ -53,7 +66,7 @@ preActionContext[ listViewArgs.activeSection - ] = [$instanceRow.data('jsonObj')]; + ] = (multiSelect ? data.jsonObj : [data.jsonObj]); if (!preAction({ context: preActionContext @@ -71,7 +84,12 @@ var context = $.extend(true, {}, listViewArgs.context); context[ listViewArgs.activeSection - ] = [$instanceRow.data('jsonObj')]; + ] = (multiSelect ? $.map($instanceRow, function(elem) { return $(elem).data('jsonObj'); }) : [$instanceRow.data('jsonObj')]); + + // Make sure the master checkbox is unselected + if (multiSelect) { + $('div.list-view').find('input.multiSelectMasterCheckbox').attr('checked', false); + } var externalLinkAction = action.externalLink; if (externalLinkAction) { @@ -165,27 +183,58 @@ // Make copy of previous row, in case data is needed $prevRow = $instanceRow.clone(); - $prevRow.data($instanceRow.data()); - - // Set loading appearance - if (args.data && !isHeader) { - $instanceRow = replaceItem( - $instanceRow, - $.extend($instanceRow.data('json-obj'), args.data), - $instanceRow.data('list-view-action-filter') - ); + if (multiSelect) { + $.each($prevRow, function(index, elem) { + $(elem).data($($instanceRow[index]).data()); + }); + } else { + $prevRow.data($instanceRow.data()); } - $instanceRow.find('td:last').children().remove(); - $instanceRow.find('td:last').append($('
').addClass('loading')); - $instanceRow.addClass('loading'); + // Set loading appearance + if (args.data && (!isHeader || multiSelect)) { + if (multiSelect) { + $instanceRow = $.map($instanceRow, function(elem, index) { + return replaceItem( + $(elem), + $.extend($(elem).data('json-obj'), args.data[index]), + $(elem).data('list-view-action-filter') + )[0]; + }); + } else { + $instanceRow = replaceItem( + $instanceRow, + $.extend($instanceRow.data('json-obj'), args.data), + $instanceRow.data('list-view-action-filter') + ); + } + } - if (options.$item) $instanceRow.data('list-view-new-item', true); + if (multiSelect) { + $.each($instanceRow, function(index, elem) { + $(elem).find('td:last').children().remove(); + $(elem).find('td:last').append($('
').addClass('loading')); + $(elem).addClass('loading'); - // Disable any clicking/actions for row - $instanceRow.bind('click', function() { - return false; - }); + if (options.$item) $(elem).data('list-view-new-item', true); + + // Disable any clicking/actions for row + $(elem).bind('click', function() { + return false; + }); + }); + } else { + $instanceRow.find('td:last').children().remove(); + $instanceRow.find('td:last').append($('
').addClass('loading')); + $instanceRow.addClass('loading'); + + if (options.$item) $instanceRow.data('list-view-new-item', true); + + // Disable any clicking/actions for row + $instanceRow.bind('click', function() { + return false; + }); + } if(args.notification) notification = args.notification; @@ -206,19 +255,41 @@ if (!args) args = {}; var actionFilter = args.actionFilter ? - args.actionFilter : $instanceRow.data('list-view-action-filter'); + args.actionFilter : (multiSelect ? + $.map($instanceRow, function(elem) { $(elem).data('list-view-action-filter') }) : + $instanceRow.data('list-view-action-filter')); - if (!isHeader) { - if ($instanceRow.is(':visible')) { + if (!isHeader || multiSelect) { + var visible = (multiSelect ? $($instanceRow[0]).is(':visible') : $instanceRow.is(':visible')); + if (visible) { if (args.data) { - $newRow = replaceItem($instanceRow, - args.data, //$.extend($instanceRow.data('json-obj'), args.data), /* $.extend($instanceRow.data('json-obj'), args.data) causes CLOUDSTACK-4687 */ - actionFilter); + if (multiSelect) { + $newRow = []; + $.each($instanceRow, function(index, elem) { + $newRow.push( + replaceItem($(elem), + args.data, //$.extend($(elem).data('json-obj'), args.data[index]), + actionFilter) + ); + }); + } else { + $newRow = replaceItem($instanceRow, + args.data, //$.extend($instanceRow.data('json-obj'), args.data), /* $.extend($instanceRow.data('json-obj'), args.data) causes CLOUDSTACK-4687 */ + actionFilter); + } } else { // Nothing new, so just put in existing data - $newRow = replaceItem($instanceRow, - $instanceRow.data('json-obj'), - actionFilter); + if (multiSelect) { + $instanceRow = $.map($instanceRow, function(elem) { + replaceItem($(elem), + $(elem).data('json-obj'), + actionFilter)[0] + }); + } else { + $newRow = replaceItem($instanceRow, + $instanceRow.data('json-obj'), + actionFilter); + } } if (needsRefresh) { @@ -262,13 +333,25 @@ } else { // For standard actions if(!args.notification) { - replaceItem( - $instanceRow, - $.extend($instanceRow.data('json-obj'), errorArgs.data), - errorArgs.actionFilter ? - errorArgs.actionFilter : - $instanceRow.data('list-view-action-filter') - ); + if (multiSelect) { + $.each($instanceRow, function(index, elem) { + replaceItem( + $(elem), + $.extend($(elem).data('json-obj'), errorArgs.data), + errorArgs.actionFilter ? + errorArgs.actionFilter : + $(elem).data('list-view-action-filter') + ); + }); + } else { + replaceItem( + $instanceRow, + $.extend($instanceRow.data('json-obj'), errorArgs.data), + errorArgs.actionFilter ? + errorArgs.actionFilter : + $instanceRow.data('list-view-action-filter') + ); + } } } } @@ -314,7 +397,7 @@ context[ listViewArgs.activeSection - ] = [$instanceRow.data('jsonObj')]; + ] = (multiSelect ? $.map($instanceRow, function(elem) { return $(elem).data('jsonObj'); }) : [$instanceRow.data('jsonObj')]); messageArgs.context = context; @@ -323,10 +406,10 @@ cloudStack.dialog.confirm({ message: messages.confirm(messageArgs), action: function() { - performAction({ - id: $instanceRow.data('list-view-item-id') - }, { - context: context + performAction(data, { + context: context, + isMultiSelectAction: multiSelect, + isHeader: args.action.isHeader }); } }); @@ -675,6 +758,7 @@ var $thead = $('
').prependTo($table).append($('')); var reorder = options.reorder; var detailView = options.detailView; + var multiSelect = options.multiSelect; var viewArgs = $table.closest('.list-view').data('view-args'); var uiCustom = viewArgs.uiCustom; var hiddenFields = []; @@ -682,6 +766,20 @@ if (preFilter != null) hiddenFields = preFilter(); + if (multiSelect) { + var $th = $('') .html(_l('label.actions')) @@ -918,6 +1016,7 @@ var rows = []; var reorder = options.reorder; var detailView = options.detailView; + var multiSelect = options.multiSelect; var $listView = $tbody.closest('.list-view'); var listViewArgs = $listView.data('view-args'); var uiCustom = listViewArgs.uiCustom; @@ -953,6 +1052,27 @@ if (preFilter != null) hiddenFields = preFilter(); + if (multiSelect) { + var $td = $('
').appendTo($thead.find('tr')); + var content = $('') + .attr('type', 'checkbox') + .addClass('multiSelectMasterCheckbox') + .appendTo($th); + + content.click(function() { + var checked = $(this).is(':checked'); + $('.multiSelectCheckbox').attr('checked', checked); + toggleMultiSelectActions(checked); + }); + } + $.each(fields, function(key) { if ($.inArray(key, hiddenFields) != -1) return true; @@ -717,7 +815,7 @@ } ); - if (actions && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) { + if (actions && !options.noActionCol && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) { $thead.find('tr').append( $('') + .appendTo($tr); + var content = $('') + .attr('type', 'checkbox') + .addClass('multiSelectCheckbox') + .click(function() { + var checked = $(this).is(':checked'); + var numRows = $(this).parents('tbody').find('input.multiSelectCheckbox').size(); + var numRowsChecked = $(this).parents('tbody').find('input.multiSelectCheckbox:checked').size(); + var enabled = checked || (numRowsChecked > 0); + toggleMultiSelectActions(enabled); + + $('input.multiSelectMasterCheckbox').attr('checked', (numRows === numRowsChecked)); + }); + + $td.append( + $('').html(content) + ); + } + // Add field data $.each(fields, function(key) { if ($.inArray(key, hiddenFields) != -1) @@ -995,8 +1115,11 @@ $td.attr('title', _s(content)); }); - - $tr.find('td:first').addClass('first'); + + var $first = $tr.find('td:first'); + if (multiSelect) + $first = $first.next(); + $first.addClass('first'); // Add reorder actions if (reorder) { @@ -1103,7 +1226,7 @@ } ); - if (actions && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) { + if (actions && !options.noActionCol && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) { var allowedActions = $.map(actions, function(value, key) { return key; }); @@ -1308,6 +1431,7 @@ if (!options) options = {}; var context = options.context; var reorder = options.reorder; + var multiSelect = options.multiSelect; var $tbody = $table.find('tbody'); if (!loadArgs) loadArgs = { @@ -1338,7 +1462,9 @@ actionFilter: args.actionFilter, context: context, reorder: reorder, - detailView: options.detailView + detailView: options.detailView, + 'multiSelect': options.multiSelect, + noActionCol: options.noActionCol }); $table.dataTable(null, { noSelect: uiCustom @@ -1494,6 +1620,7 @@ var page = 1; var actions = listViewData.actions; var reorder = listViewData.reorder; + var multiSelect = listViewData.multiSelect; var tableHeight = $table.height(); var endTable = false; var setEndTable = function() { @@ -1557,14 +1684,18 @@ }) )) return true; - $toolbar - .append( - $('
') - .addClass('button action main-action reduced-hide').addClass(actionName) - .data('list-view-action-id', actionName) - .append($('').addClass('icon')) - .append($('').html(_l(action.label))) - ); + var $action = $('
') + .addClass('button action main-action reduced-hide').addClass(actionName) + .data('list-view-action-id', actionName) + .append($('').addClass('icon')) + .append($('').html(_l(action.label))); + + if (action.isMultiSelectAction) { + $action.addClass('multiSelectAction'); + $action.hide(); + } + + $toolbar.append($action) return true; }); @@ -1577,7 +1708,9 @@ $table, listViewData.actions, { reorder: reorder, - detailView: listViewData.detailView + detailView: listViewData.detailView, + 'multiSelect': multiSelect, + noActionCol: listViewData.noActionCol }); createFilters($toolbar, listViewData.filters); createSearchBar($toolbar, listViewData); @@ -1602,7 +1735,9 @@ context: args.context, reorder: reorder, detailView: listViewData.detailView, - setEndTable: setEndTable + setEndTable: setEndTable, + 'multiSelect': multiSelect, + noActionCol: listViewData.noActionCol } ); @@ -1654,7 +1789,9 @@ context: $listView.data('view-args').context, reorder: listViewData.reorder, detailView: listViewData.detailView, - setEndTable: setEndTable + setEndTable: setEndTable, + 'multiSelect': multiSelect, + noActionCol: listViewData.noActionCol } ); }; @@ -1703,7 +1840,9 @@ context: $listView.data('view-args').context, reorder: listViewData.reorder, detailView: listViewData.detailView, - setEndTable: setEndTable + setEndTable: setEndTable, + 'multiSelect': multiSelect, + noActionCol: listViewData.noActionCol } ); }; @@ -1793,7 +1932,9 @@ }, actions, { reorder: listViewData.reorder, detailView: listViewData.detailView, - setEndTable: setEndTable + setEndTable: setEndTable, + 'multiSelect': multiSelect, + noActionCol: listViewData.noActionCol }); $table.height() == tableHeight ? endTable = true : tableHeight = $table.height(); } @@ -1824,8 +1965,7 @@ var id = $target.closest('tr').data('list-view-item-id'); var jsonObj = $target.closest('tr').data('jsonObj'); var detailViewArgs; - var detailViewPresent = ($target.closest('div.data-table tr td').size() && - $target.closest('div.data-table tr td').index() == 0 && + var detailViewPresent = ($target.closest('div.data-table tr td.first').size() && listViewData.detailView && !$target.closest('div.edit').size()); var uiCustom = args.uiCustom == true ? true : false; @@ -1896,10 +2036,14 @@ } if ($target.closest('.action.add').size() || - $target.closest('.action.main-action').size()) { + $target.closest('.action.main-action:not(.multiSelectAction)').size()) { $tr = $target.closest('div.list-view').find('tr:first'); // Dummy row } else { - $tr = $target.closest('tr'); + if (listViewData.actions[actionID].isMultiSelectAction) { + $tr = $('div.list-view').find('input.multiSelectCheckbox:checked').parents('tr'); + } else { + $tr = $target.closest('tr'); + } } var uiCallback = uiActions[actionID]; @@ -1960,7 +2104,9 @@ prepend: true, actionFilter: actionFilter, reorder: reorder, - detailView: targetArgs.detailView + detailView: targetArgs.detailView, + 'multiSelect': targetArgs.multiSelect, + noActionCol: targetArgs.noActionCol } )[0]; listView.find('table').dataTable('refresh'); @@ -1980,6 +2126,7 @@ listViewArgs.activeSection ].listView : listViewArgs; var reorder = targetArgs.reorder; + var multiSelect = targetArgs.multiSelect; var $table = $row.closest('table'); var defaultActionFilter = $row.data('list-view-action-filter'); @@ -1991,7 +2138,9 @@ targetArgs.actions, { actionFilter: actionFilter ? actionFilter : defaultActionFilter, reorder: reorder, - detailView: targetArgs.detailView + detailView: targetArgs.detailView, + 'multiSelect': multiSelect, + noActionCol: targetArgs.noActionCol } )[0]; @@ -2004,6 +2153,13 @@ return $newRow; }; + var toggleMultiSelectActions = function(enabled) { + var $listView = $('div.list-view'); + $listView.find('div.action.add')[enabled ? 'hide' : 'show'](); + $listView.find('div.main-action:not(.multiSelectAction)')[enabled ? 'hide' : 'show'](); + $listView.find('div.main-action.multiSelectAction')[enabled ? 'show' : 'hide'](); + } + $.fn.listView = function(args, options) { if (!options) options = {}; if (args == 'prependItem') { diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatacenterMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatacenterMO.java index 1844b6ad37a..03ba2b75db3 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatacenterMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatacenterMO.java @@ -20,6 +20,8 @@ package com.cloud.hypervisor.vmware.mo; import java.util.ArrayList; import java.util.List; +import org.apache.log4j.Logger; + import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.utils.Pair; import com.vmware.vim25.CustomFieldStringValue; @@ -37,6 +39,7 @@ import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo; import java.util.Arrays; public class DatacenterMO extends BaseMO { + private static final Logger s_logger = Logger.getLogger(DatacenterMO.class); public DatacenterMO(VmwareContext context, ManagedObjectReference morDc) { super(context, morDc); @@ -50,7 +53,9 @@ public class DatacenterMO extends BaseMO { super(context, null); _mor = _context.getVimClient().getDecendentMoRef(_context.getRootFolder(), "Datacenter", dcName); - assert(_mor != null); + if(_mor == null) { + s_logger.error("Unable to locate DC " + dcName); + } } @Override @@ -61,7 +66,6 @@ public class DatacenterMO extends BaseMO { public void registerTemplate(ManagedObjectReference morHost, String datastoreName, String templateName, String templateFileName) throws Exception { - ManagedObjectReference morFolder = (ManagedObjectReference)_context.getVimClient().getDynamicProperty( _mor, "vmFolder"); assert(morFolder != null); diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java index d4e4256ebde..b20217a5b9f 100644 --- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java @@ -107,7 +107,6 @@ public class VmwareClient { } private ManagedObjectReference SVC_INST_REF = new ManagedObjectReference(); - private ManagedObjectReference propCollectorRef; private static VimService vimService; private VimPortType vimPort; private String serviceCookie; @@ -151,8 +150,6 @@ public class VmwareClient { vimPort.login(serviceContent.getSessionManager(), userName, password, null); isConnected = true; - - propCollectorRef = serviceContent.getPropertyCollector(); } /** @@ -197,7 +194,7 @@ public class VmwareClient { * @return Service property collector */ public ManagedObjectReference getPropCol() { - return propCollectorRef; + return getServiceContent().getPropertyCollector(); } /** @@ -207,6 +204,43 @@ public class VmwareClient { return getServiceContent().getRootFolder(); } + public boolean validate() { + // + // There is no official API to validate an open vCenter API session. This is hacking way to tell if + // an open vCenter API session is still valid for making calls. + // + // It will give false result if there really does not exist data-center in the inventory, however, I consider + // this really is not possible in production deployment + // + + // Create PropertySpecs + PropertySpec pSpec = new PropertySpec(); + pSpec.setType("Datacenter"); + pSpec.setAll(false); + pSpec.getPathSet().add("name"); + + ObjectSpec oSpec = new ObjectSpec(); + oSpec.setObj(getRootFolder()); + oSpec.setSkip(false); + oSpec.getSelectSet().addAll(constructCompleteTraversalSpec()); + + PropertyFilterSpec spec = new PropertyFilterSpec(); + spec.getPropSet().add(pSpec); + spec.getObjectSet().add(oSpec); + List specArr = new ArrayList(); + specArr.add(spec); + + try { + List ocary = vimPort.retrieveProperties(getPropCol(), specArr); + if(ocary != null && ocary.size() > 0) + return true; + } catch(Exception e) { + return false; + } + + return false; + } + /** * Get the property value of a managed object. * @@ -266,7 +300,7 @@ public class VmwareClient { List specArr = new ArrayList(); specArr.add(spec); - return vimPort.retrieveProperties(propCollectorRef, specArr); + return vimPort.retrieveProperties(getPropCol(), specArr); } /** @@ -334,7 +368,8 @@ public class VmwareClient { pSpec.setType(objmor.getType()); spec.getPropSet().add(pSpec); - ManagedObjectReference filterSpecRef = vimPort.createFilter(propCollectorRef, spec, true); + ManagedObjectReference propertyCollector = this.getPropCol(); + ManagedObjectReference filterSpecRef = vimPort.createFilter(propertyCollector, spec, true); boolean reached = false; @@ -343,7 +378,7 @@ public class VmwareClient { List objupary = null; List propchgary = null; while (!reached) { - updateset = vimPort.waitForUpdates(propCollectorRef, version); + updateset = vimPort.waitForUpdates(propertyCollector, version); if (updateset == null || updateset.getFilterSet() == null) { continue; } @@ -546,7 +581,7 @@ public class VmwareClient { List specArr = new ArrayList(); specArr.add(spec); - List ocary = vimPort.retrieveProperties(propCollectorRef, specArr); + List ocary = vimPort.retrieveProperties(getPropCol(), specArr); if (ocary == null || ocary.size() == 0) { return null; diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java index 6c3dab7f790..c499576f5f5 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java @@ -102,6 +102,10 @@ public class VmwareContext { if(s_logger.isInfoEnabled()) s_logger.info("New VmwareContext object, current outstanding count: " + getOutstandingContextCount()); } + + public boolean validate() { + return _vimClient.validate(); + } public void registerStockObject(String name, Object obj) { synchronized(_stockMap) {