From dabd85e153e2a46e243cba4b06dd13c5674a84b5 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Fri, 27 Jul 2012 15:07:36 -0700 Subject: [PATCH 01/66] CS-15717: fail to delete the network when corresponding network elements fail to be destroyed --- server/src/com/cloud/network/NetworkManagerImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index c96ea52b299..83acc9b9c35 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -3215,7 +3215,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.debug("Sending destroy to " + element); } - element.destroy(network); + if (!element.destroy(network)) { + success = false; + s_logger.warn("Unable to complete destroy of the network: failed to destroy network element " + element.getName()); + } } catch (ResourceUnavailableException e) { s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e); success = false; @@ -3225,7 +3228,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } catch (Exception e) { s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e); success = false; - } + } } } From 4dd2854d614a49e19f4c802a9dfa02ac96c6827b Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 27 Jul 2012 08:44:17 +0200 Subject: [PATCH 02/66] rbd: Small JavaScript fix --- ui/scripts/sharedFunctions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index c4cf58c86e5..a81c4270b21 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -482,8 +482,8 @@ function rbdURL(monitor, pool, id, secret) { Replace the + and / symbols by - and _ to have URL-safe base64 going to the API It's hacky, but otherwise we'll confuse java.net.URI which splits the incoming URI */ - secret = str.replace("+", "-"); - secret = str.replace("/", "_"); + secret = secret.replace("+", "-"); + secret = secret.replace("/", "_"); if (id != null && secret != null) { monitor = id + ":" + secret + "@" + monitor; From 5789cd94a5468414d105f5cabffa5ec382f25347 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 27 Jul 2012 08:53:44 +0200 Subject: [PATCH 03/66] setup: Update 3.0.3 to 4.0.0 SQL update file I noticed that we have pending changes for the resource tags and Nicira integration. Adding them as a precaution, so they don't get lost. --- setup/db/db/schema-303to40.sql | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/setup/db/db/schema-303to40.sql b/setup/db/db/schema-303to40.sql index 87dd1d3c789..01710b10736 100644 --- a/setup/db/db/schema-303to40.sql +++ b/setup/db/db/schema-303to40.sql @@ -19,4 +19,45 @@ -- Schema upgrade from 3.0.3 to 4.0.0; --; +# RBD Primary Storage pool support (commit: 406fd95d87bfcdbb282d65589ab1fb6e9fd0018a) ALTER TABLE `storage_pool` ADD `user_info` VARCHAR( 255 ) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems' AFTER `host_address`; + +# Resource tags (commit: 62d45b9670520a1ee8b520509393d4258c689b50) +CREATE TABLE `cloud`.`resource_tags` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `uuid` varchar(40), + `key` varchar(255), + `value` varchar(255), + `resource_id` bigint unsigned NOT NULL, + `resource_uuid` varchar(40), + `resource_type` varchar(255), + `customer` varchar(255), + `domain_id` bigint unsigned NOT NULL COMMENT 'foreign key to domain id', + `account_id` bigint unsigned NOT NULL COMMENT 'owner of this network', + PRIMARY KEY (`id`), + CONSTRAINT `fk_tags__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`), + CONSTRAINT `fk_tags__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`), + UNIQUE `i_tags__resource_id__resource_type__key`(`resource_id`, `resource_type`, `key`), + CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +# Nicira Integration (commit: 79c7da07abd4294f150851aa0c2d06a28564c5a9) +CREATE TABLE `cloud`.`external_nicira_nvp_devices` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(255) UNIQUE, + `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which nicira nvp device is added', + `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this nicira nvp device', + `device_name` varchar(255) NOT NULL COMMENT 'name of the nicira nvp device', + `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external nicira nvp device', + PRIMARY KEY (`id`), + CONSTRAINT `fk_external_nicira_nvp_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_external_nicira_nvp_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `logicalswitch` varchar(255) NOT NULL COMMENT 'nicira uuid of logical switch this port is provisioned on', + `logicalswitchport` varchar(255) UNIQUE COMMENT 'nicira uuid of this logical switch port', + `nic` varchar(255) UNIQUE COMMENT 'cloudstack uuid of the nic connected to this logical switch port', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; From 3f4e906b1dd20c29f28329284aa9e024f2ab4311 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 27 Jul 2012 09:01:15 +0200 Subject: [PATCH 04/66] agent: Remove cloud-cleanup.conf for Ubuntu This is a very dangerous file. Although we do not package it, it would be very dangerous to do so. If this file would be present on a HyperVisor it would cause all instances to be stopped on a libvirt restart. There is no need for stopping all instances when libvirt is being stopped (or restarted). --- .../ubuntu/SYSCONFDIR/init/cloud-cleanup.conf | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 agent/distro/ubuntu/SYSCONFDIR/init/cloud-cleanup.conf diff --git a/agent/distro/ubuntu/SYSCONFDIR/init/cloud-cleanup.conf b/agent/distro/ubuntu/SYSCONFDIR/init/cloud-cleanup.conf deleted file mode 100644 index 71131e7c55c..00000000000 --- a/agent/distro/ubuntu/SYSCONFDIR/init/cloud-cleanup.conf +++ /dev/null @@ -1,32 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -description "Stop CloudStack VMs on shutdown" -author "Manuel Amador (Rudd-O) " - -start on stopping libvirt-bin - -task -script - curr_runlevel=`runlevel | tail -c 2` - if [ "$curr_runlevel" = "6" -o "$curr_runlevel" = "0" ] ; then - for a in `virsh list | awk ' /^ +[0-9]+ [vri]-([0-9]+?)-/ { print $2 } '` ; do - echo Destroying CloudStack VM $a - virsh destroy $a - done - fi -end script From 9d67ecdbb75603dae3469c80871f4fae584ccafb Mon Sep 17 00:00:00 2001 From: olgasmola Date: Fri, 27 Jul 2012 15:36:58 +0300 Subject: [PATCH 05/66] CS-15518: Fix password field garbling on login screen. --- ui/scripts/ui-custom/login.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ui/scripts/ui-custom/login.js b/ui/scripts/ui-custom/login.js index 72b3c6c728a..20e6abff2b2 100644 --- a/ui/scripts/ui-custom/login.js +++ b/ui/scripts/ui-custom/login.js @@ -38,6 +38,17 @@ $login.appendTo('html body'); $('html body').addClass('login'); + // Remove label if field was auto filled + $.each($form.find('label'), function() { + var $label = $(this); + var $input = $form.find('input').filter(function() { + return $(this).attr('name') == $label.attr('for'); + }); + if ($input.val()) { + $label.hide(); + } + }); + // Form validation $form.validate(); From 0be4230f91115a65d8fe8644b1fe50709a2114d9 Mon Sep 17 00:00:00 2001 From: olgasmola Date: Fri, 27 Jul 2012 16:27:59 +0300 Subject: [PATCH 06/66] CS-15325: Fix selected name of user from the drop down list overlay. --- ui/css/cloudstack3.css | 2 ++ ui/scripts/ui-custom/login.js | 19 +++++++++++++------ ui/scripts/ui/core.js | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index a60e4807ca2..876d6633530 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -280,6 +280,8 @@ body.login { .login .fields .field label.error { color: #FF0000; float: right; + left: 204px; + top: 0; } .login .fields input { diff --git a/ui/scripts/ui-custom/login.js b/ui/scripts/ui-custom/login.js index 20e6abff2b2..c092b82ec0e 100644 --- a/ui/scripts/ui-custom/login.js +++ b/ui/scripts/ui-custom/login.js @@ -53,7 +53,7 @@ $form.validate(); // Form label behavior - $inputs.bind('keydown keyup focus blur', function(event) { + $inputs.bind('keydown focus click blur', function(event) { var $target = $(event.target); var $label = $form.find('label').filter(function() { return $(this).attr('for') == $target.attr('name'); @@ -63,11 +63,16 @@ $label.hide(); return true; - } else { - if (!$target.val()) { + } else if (event.type == 'blur') { + if ($target.hasClass('first-input')) { + $target.removeClass('first-input'); + } + if (!$(this).val()) { $label.show(); - } else { - $label.hide(); + } + } else { + if (!$target.hasClass('first-input')) { + $label.hide(); } } @@ -79,11 +84,13 @@ // Labels cause related input to be focused $login.find('label').click(function() { var $input = $inputs.filter('[name=' + $(this).attr('for') + ']'); + var $label = $(this); $input.focus(); + $label.hide(); }); - $inputs.filter(':first').focus(); + $inputs.filter(':first').addClass('first-input').focus(); // Login action $login.find('input[type=submit]').click(function() { diff --git a/ui/scripts/ui/core.js b/ui/scripts/ui/core.js index b7ffdba2328..0c6b4e744c7 100644 --- a/ui/scripts/ui/core.js +++ b/ui/scripts/ui/core.js @@ -352,7 +352,7 @@ // Check if target should be hovered function checkHoveredLabel($target) { var $multiWizard = $('div.ui-dialog div.multi-wizard'); - if ($target.is('label[for]') || + if (($target.is('label[for]') && !$target.parents('body.login')) || ($multiWizard.size() && ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) || ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size()) From 12c7fb36258688c93d1a95e0d0182498ee15ae95 Mon Sep 17 00:00:00 2001 From: olgasmola Date: Fri, 27 Jul 2012 16:36:02 +0300 Subject: [PATCH 07/66] Fix build script typo. --- plugins/deployment-planners/user-concentrated-pod/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/deployment-planners/user-concentrated-pod/build.xml b/plugins/deployment-planners/user-concentrated-pod/build.xml index 29d4595b4a2..d63f33476b3 100755 --- a/plugins/deployment-planners/user-concentrated-pod/build.xml +++ b/plugins/deployment-planners/user-concentrated-pod/build.xml @@ -105,7 +105,7 @@ - + From 82bb1e5592d5a15b12215c79bcc4245b3c1e9878 Mon Sep 17 00:00:00 2001 From: olgasmola Date: Fri, 27 Jul 2012 17:32:54 +0300 Subject: [PATCH 08/66] CS-15349: Fix incorrect result when Make owner in New project/Add account. --- ui/scripts/projects.js | 28 ++++++++++++++++++++++++++-- ui/scripts/ui/widgets/multiEdit.js | 6 ++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/ui/scripts/projects.js b/ui/scripts/projects.js index 2ece194e014..cbbb4cef8a2 100644 --- a/ui/scripts/projects.js +++ b/ui/scripts/projects.js @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. (function(cloudStack) { + var getProjectAdmin; cloudStack.projects = { requireInvitation: function(args) { return g_capabilities.projectinviterequired; @@ -447,12 +448,28 @@ return ['destroy']; } - if (args.context.multiRule[0].role != 'Admin') { + if (args.context.multiRule[0].role != 'Admin' && + (cloudStack.context.users[0].account == getProjectAdmin || isAdmin() || isDomainAdmin())) { // This is for the new project wizard: check if current logged in User is the Project Owner return args.context.actions; } return []; }, + readOnlyCheck: function(args) { // check if current logged in User is the Project Owner + if (isAdmin() || isDomainAdmin()) + return true; + + var projectOwner, currentUser = cloudStack.context.users[0].account; + $(args.data).each(function() { + var data = this; + if (data.role == 'Admin') + projectOwner = data.username; + }); + if (projectOwner == currentUser) + return true; + + return false; + }, actions: { destroy: { label: 'label.remove.project.account', @@ -497,7 +514,12 @@ success: function(data) { args.response.success({ _custom: { - jobId: data.updateprojectresponse.jobid + jobId: data.updateprojectresponse.jobid, + onComplete: function(){ + setTimeout(function() { + $(window).trigger('cloudStack.fullRefresh'); + }, 500); + } }, notification: { label: 'label.make.project.owner', @@ -522,6 +544,8 @@ success: function(data) { args.response.success({ data: $.map(data.listprojectaccountsresponse.projectaccount, function(elem) { + if (elem.role == 'Owner' || elem.role == 'Admin') + getProjectAdmin = elem.account; return { id: elem.accountid, role: elem.role, diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index 140b889a76b..93342141425 100644 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -675,6 +675,7 @@ var context = args.context; var ignoreEmptyFields = args.ignoreEmptyFields; var actionPreFilter = args.actionPreFilter; + var readOnlyCheck = args.readOnlyCheck; var $thead = $('').appendTo( $('').appendTo($inputTable) @@ -935,6 +936,11 @@ ).appendTo($dataBody); }); + if (readOnlyCheck && !readOnlyCheck(args)) { + $multi.find('th.add-user, td.add-user').detach(); + $multiForm.find('tbody').detach(); + } + _medit.refreshItemWidths($multi); }, error: cloudStack.dialog.error From 9c895b14ab88898cced31139759152fd0006103d Mon Sep 17 00:00:00 2001 From: olgasmola Date: Fri, 27 Jul 2012 18:23:07 +0300 Subject: [PATCH 09/66] CS-15317: Fix operations with accounts on the Project tab after making another account project owner. --- ui/scripts/projects.js | 31 ++++++++++++++++-- ui/scripts/ui/widgets/detailView.js | 50 ++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/ui/scripts/projects.js b/ui/scripts/projects.js index cbbb4cef8a2..293a2b01105 100644 --- a/ui/scripts/projects.js +++ b/ui/scripts/projects.js @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. (function(cloudStack) { - var getProjectAdmin; + var getProjectAdmin, selectedProjectObj; cloudStack.projects = { requireInvitation: function(args) { return g_capabilities.projectinviterequired; @@ -518,6 +518,9 @@ onComplete: function(){ setTimeout(function() { $(window).trigger('cloudStack.fullRefresh'); + if (isUser()) { + $(window).trigger('cloudStack.detailsRefresh'); + } }, 500); } }, @@ -659,6 +662,30 @@ }, detailView: { + updateContext: function (args) { + var project; + var projectID = args.context.projects[0].id; + var url = 'listProjects'; + if (isDomainAdmin()) { + url += '&domainid=' + args.context.users[0].domainid; + } + $.ajax({ + url: createURL(url), + data: { + listAll: true, + id: projectID + }, + async: false, + success: function(json) { + project = json.listprojectsresponse.project[0]; // override project after update owner + } + }); + selectedProjectObj = project; + + return { + projects: [project] + }; + }, actions: { edit: { label: 'label.edit', @@ -782,7 +809,7 @@ }, tabFilter: function(args) { - var project = args.context.projects[0]; + var project = selectedProjectObj; var projectOwner = project.account; var currentAccount = args.context.users[0].account; var hiddenTabs = []; diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index b792bcf32ac..eb39b80c05a 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -1038,7 +1038,7 @@ ); }; - var replaceTabs = function($detailView, $newTabs, tabs, options) { + var replaceTabs = function($detailView, tabs, options) { var $detailViewElems = $detailView.find('ul.ui-tabs-nav, .detail-group'); $detailView.tabs('destroy'); $detailViewElems.remove(); @@ -1057,25 +1057,32 @@ ); }; - $.fn.detailView = function(args) { + $.fn.detailView = function(args, options) { var $detailView = this; + + if (options == 'refresh') { + var $tabs = replaceTabs($detailView, args.tabs, { + context: args.context, + tabFilter: args.tabFilter + }); + } else { + $detailView.addClass('detail-view'); + $detailView.data('view-args', args); - $detailView.addClass('detail-view'); - $detailView.data('view-args', args); + if (args.$listViewRow) { + $detailView.data('list-view-row', args.$listViewRow); + } - if (args.$listViewRow) { - $detailView.data('list-view-row', args.$listViewRow); + // Create toolbar + var $toolbar = makeToolbar().appendTo($detailView); + + // Create tabs + var $tabs = makeTabs($detailView, args.tabs, { + context: args.context, + tabFilter: args.tabFilter + }).appendTo($detailView); } - // Create toolbar - var $toolbar = makeToolbar().appendTo($detailView); - - // Create tabs - var $tabs = makeTabs($detailView, args.tabs, { - context: args.context, - tabFilter: args.tabFilter - }).appendTo($detailView); - $detailView.tabs(); return $detailView; @@ -1154,4 +1161,17 @@ return true; }); + + // Detail view refresh handler + $(window).bind('cloudStack.detailsRefresh', function() { + var $detailView = $('.detail-view'); + + $detailView.each(function() { + var $detailView = $(this), + args = $detailView.data('view-args'); + + $detailView.detailView(args, 'refresh'); + }); + }); + }(window.jQuery, window.cloudStack, window._l)); From c89455592490d6219f445e8e893559e52b83ff1b Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 27 Jul 2012 18:06:38 +0200 Subject: [PATCH 10/66] setup: Add database upgrade for 3.0.3 to 4.0 Also added a upgrade path from 3.X.X to 4.0, this should work. --- .../cloud/upgrade/DatabaseUpgradeChecker.java | 13 ++-- .../com/cloud/upgrade/dao/Upgrade303to40.java | 67 +++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 server/src/com/cloud/upgrade/dao/Upgrade303to40.java diff --git a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java index 88577ea89ab..eb7a11c63e6 100755 --- a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -55,6 +55,7 @@ import com.cloud.upgrade.dao.Upgrade229to2210; import com.cloud.upgrade.dao.Upgrade301to302; import com.cloud.upgrade.dao.Upgrade302to303; import com.cloud.upgrade.dao.Upgrade30to301; +import com.cloud.upgrade.dao.Upgrade303to40; import com.cloud.upgrade.dao.UpgradeSnapshot217to224; import com.cloud.upgrade.dao.UpgradeSnapshot223to224; import com.cloud.upgrade.dao.VersionDao; @@ -152,11 +153,13 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { _upgradeMap.put("2.2.14", new DbUpgrade[] { new Upgrade2214to30(), new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303() }); - _upgradeMap.put("3.0.0", new DbUpgrade[] { new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303() }); - - _upgradeMap.put("3.0.1", new DbUpgrade[] { new Upgrade301to302(), new Upgrade302to303() }); - - _upgradeMap.put("3.0.2", new DbUpgrade[] { new Upgrade302to303() }); + _upgradeMap.put("3.0.0", new DbUpgrade[] { new Upgrade30to301(), new Upgrade301to302(), new Upgrade302to303(), new Upgrade303to40() }); + + _upgradeMap.put("3.0.1", new DbUpgrade[] { new Upgrade301to302(), new Upgrade302to303(), new Upgrade303to40() }); + + _upgradeMap.put("3.0.2", new DbUpgrade[] { new Upgrade302to303(), new Upgrade303to40() }); + + _upgradeMap.put("3.0.3", new DbUpgrade[] { new Upgrade303to40() }); } protected void runScript(Connection conn, File file) { diff --git a/server/src/com/cloud/upgrade/dao/Upgrade303to40.java b/server/src/com/cloud/upgrade/dao/Upgrade303to40.java new file mode 100644 index 00000000000..864d58dc4a6 --- /dev/null +++ b/server/src/com/cloud/upgrade/dao/Upgrade303to40.java @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +package com.cloud.upgrade.dao; + +/** + * @author Alena Prokharchyk + */ +import java.io.File; +import java.sql.Connection; + +import org.apache.log4j.Logger; +// +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +public class Upgrade303to40 implements DbUpgrade { + final static Logger s_logger = Logger.getLogger(Upgrade303to40.class); + + @Override + public String[] getUpgradableVersionRange() { + return new String[] { "3.0.3", "4.0.0" }; + } + + @Override + public String getUpgradedVersion() { + return "4.0.0"; + } + + @Override + public boolean supportsRollingUpgrade() { + return false; + } + + @Override + public File[] getPrepareScripts() { + String script = Script.findScript("", "db/schema-303to40.sql"); + if (script == null) { + throw new CloudRuntimeException("Unable to find db/schema-303to40.sql"); + } + + return new File[] { new File(script) }; + } + + @Override + public void performDataMigration(Connection conn) { + } + + @Override + public File[] getCleanupScripts() { + return null; + } +} From 9611a017e931750891c46c38883d919ce3e70cd4 Mon Sep 17 00:00:00 2001 From: kishan Date: Thu, 28 Jun 2012 18:06:30 -0700 Subject: [PATCH 11/66] bug CS-15389: Added prepareStop to Virtualmachine manager and moved network usage collection into prepareStop of VR manager --- .../agent/manager/MockVmManagerImpl.java | 4 +- .../cloud/resource/AgentRoutingResource.java | 4 +- .../computing/FakeComputingResource.java | 11 +- .../computing/LibvirtComputingResource.java | 25 +--- api/src/com/cloud/agent/api/RebootAnswer.java | 33 +---- api/src/com/cloud/agent/api/StopAnswer.java | 8 +- api/src/com/cloud/agent/api/StopCommand.java | 10 -- .../cloud/ovm/hypervisor/OvmResourceBase.java | 10 +- .../vmware/resource/VmwareResource.java | 40 ++---- .../xen/resource/CitrixResourceBase.java | 44 ++---- .../lb/ElasticLoadBalancerManagerImpl.java | 5 + .../baremetal/BareMetalResourceBase.java | 6 +- .../AgentBasedConsoleProxyManager.java | 4 + .../consoleproxy/ConsoleProxyManagerImpl.java | 4 + .../VirtualNetworkApplianceManagerImpl.java | 126 ++++++++++++++---- .../SecondaryStorageManagerImpl.java | 5 + .../src/com/cloud/vm/UserVmManagerImpl.java | 3 + .../src/com/cloud/vm/VirtualMachineGuru.java | 7 + .../cloud/vm/VirtualMachineManagerImpl.java | 9 +- 19 files changed, 183 insertions(+), 175 deletions(-) diff --git a/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java index dca44c46716..5e66464e66b 100644 --- a/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java +++ b/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java @@ -352,12 +352,12 @@ public class MockVmManagerImpl implements MockVmManager { _mockAgentMgr.handleSystemVMStop(vm.getId()); } - return new StopAnswer(cmd, null, new Integer(0), new Long(100), new Long(200)); + return new StopAnswer(cmd, null, new Integer(0), true); } @Override public Answer rebootVM(RebootCommand cmd) { - return new RebootAnswer(cmd, "Rebooted "+cmd.getVmName()); + return new RebootAnswer(cmd, "Rebooted "+cmd.getVmName(), false); } @Override diff --git a/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java b/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java index e259c39f3a7..291e46a0bed 100644 --- a/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java +++ b/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java @@ -233,10 +233,10 @@ public class AgentRoutingResource extends AgentStorageResource { Answer result = _simMgr.simulate(cmd, hostGuid); if (!result.getResult()) { - return new StopAnswer(cmd, result.getDetails()); + return new StopAnswer(cmd, result.getDetails(), false); } - answer = new StopAnswer(cmd, null, 0, new Long(100), new Long(200)); + answer = new StopAnswer(cmd, null, 0, true); Pair data = _runningVms.get(vmName); if (data != null) { this.usedCpu -= data.first(); diff --git a/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java b/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java index d9b5d949c44..abfa4787a51 100644 --- a/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java @@ -443,8 +443,6 @@ public class FakeComputingResource extends ServerResourceBase implements String vmName = cmd.getVmName(); Integer port = vmMgr.getVncPort(vmName); - Long bytesReceived = null; - Long bytesSent = null; State state = null; synchronized (_vms) { @@ -462,17 +460,16 @@ public class FakeComputingResource extends ServerResourceBase implements s_logger.warn("Couldn't stop " + vmName); if (result != null) { - return new StopAnswer(cmd, result); + return new StopAnswer(cmd, result, false); } } - answer = new StopAnswer(cmd, null, port, bytesSent, bytesReceived); + answer = new StopAnswer(cmd, null, port, true); String result2 = vmMgr.cleanupVnet(cmd.getVnet()); if (result2 != null) { result = result2 + (result != null ? ("\n" + result) : ""); - answer = new StopAnswer(cmd, result, port, bytesSent, - bytesReceived); + answer = new StopAnswer(cmd, result, port, true); } _dhcpSnooper.cleanup(vmName, null); @@ -498,7 +495,7 @@ public class FakeComputingResource extends ServerResourceBase implements protected Answer execute(RebootCommand cmd) { VmMgr vmMgr = getVmManager(); vmMgr.rebootVM(cmd.getVmName()); - return new RebootAnswer(cmd, "success", 0L, 0L); + return new RebootAnswer(cmd, "success", true); } private Answer execute(PingTestCommand cmd) { diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 347ff87ac9d..a4854bec394 100755 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -2270,8 +2270,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements } private Answer execute(RebootCommand cmd) { - Long bytesReceived = null; - Long bytesSent = null; synchronized (_vms) { _vms.put(cmd.getVmName(), State.Starting); @@ -2288,13 +2286,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements } get_rule_logs_for_vms(); - return new RebootAnswer(cmd, null, bytesSent, bytesReceived, - vncPort); + return new RebootAnswer(cmd, null, vncPort); } else { - return new RebootAnswer(cmd, result); + return new RebootAnswer(cmd, result, false); } } catch (LibvirtException e) { - return new RebootAnswer(cmd, e.getMessage()); + return new RebootAnswer(cmd, e.getMessage(), false); } finally { synchronized (_vms) { _vms.put(cmd.getVmName(), State.Running); @@ -2303,16 +2300,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements } protected Answer execute(RebootRouterCommand cmd) { - Long bytesSent = 0L; - Long bytesRcvd = 0L; - if (VirtualMachineName.isValidRouterName(cmd.getVmName())) { - long[] stats = getNetworkStats(cmd.getPrivateIpAddress()); - bytesSent = stats[0]; - bytesRcvd = stats[1]; - } RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); - answer.setBytesSent(bytesSent); - answer.setBytesReceived(bytesRcvd); String result = _virtRouterResource.connect(cmd.getPrivateIpAddress()); if (result == null) { networkUsage(cmd.getPrivateIpAddress(), "create", null); @@ -2345,9 +2333,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements protected Answer execute(StopCommand cmd) { final String vmName = cmd.getVmName(); - Long bytesReceived = new Long(0); - Long bytesSent = new Long(0); - State state = null; synchronized (_vms) { state = _vms.get(vmName); @@ -2373,9 +2358,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements result = result2 + result; } state = State.Stopped; - return new StopAnswer(cmd, result, 0, bytesSent, bytesReceived); + return new StopAnswer(cmd, result, 0, true); } catch (LibvirtException e) { - return new StopAnswer(cmd, e.getMessage()); + return new StopAnswer(cmd, e.getMessage(), false); } finally { synchronized (_vms) { if (state != null) { diff --git a/api/src/com/cloud/agent/api/RebootAnswer.java b/api/src/com/cloud/agent/api/RebootAnswer.java index b69afb22bbd..da53b4fb1a3 100644 --- a/api/src/com/cloud/agent/api/RebootAnswer.java +++ b/api/src/com/cloud/agent/api/RebootAnswer.java @@ -17,52 +17,25 @@ package com.cloud.agent.api; public class RebootAnswer extends Answer { - Long bytesSent; - Long bytesReceived; Integer vncPort; protected RebootAnswer() { } - public RebootAnswer(RebootCommand cmd, String details, Long bytesSent, Long bytesReceived, Integer vncport) { + public RebootAnswer(RebootCommand cmd, String details, Integer vncport) { super(cmd, true, details); - this.bytesReceived = bytesReceived; - this.bytesSent = bytesSent; this.vncPort = vncport; } - public RebootAnswer(RebootCommand cmd, String details, Long bytesSent, Long bytesReceived) { - super(cmd, true, details); - this.bytesReceived = bytesReceived; - this.bytesSent = bytesSent; + public RebootAnswer(RebootCommand cmd, String details, boolean success) { + super(cmd, success, details); this.vncPort = null; } - public RebootAnswer(RebootCommand cmd, String details) { - super(cmd, false, details); - bytesSent = null; - bytesReceived = null; - } - public RebootAnswer(RebootCommand cmd, Exception e) { super(cmd, e); } - public void setBytesReceived(Long bytesReceived) { - this.bytesReceived = bytesReceived; - } - - public Long getBytesReceived() { - return bytesReceived; - } - - public void setBytesSent(Long bytesSent) { - this.bytesSent = bytesSent; - } - - public Long getBytesSent() { - return bytesSent; - } public Integer getVncPort() { return vncPort; } diff --git a/api/src/com/cloud/agent/api/StopAnswer.java b/api/src/com/cloud/agent/api/StopAnswer.java index 4050cd37d03..52f28f165f2 100755 --- a/api/src/com/cloud/agent/api/StopAnswer.java +++ b/api/src/com/cloud/agent/api/StopAnswer.java @@ -22,13 +22,13 @@ public class StopAnswer extends RebootAnswer { protected StopAnswer() { } - public StopAnswer(StopCommand cmd, String details, Integer vncPort, Long bytesSent, Long bytesReceived) { - super(cmd, details, bytesSent, bytesReceived); + public StopAnswer(StopCommand cmd, String details, Integer vncPort, boolean success) { + super(cmd, details, success); this.vncPort = vncPort; } - public StopAnswer(StopCommand cmd, String details) { - super(cmd, details); + public StopAnswer(StopCommand cmd, String details, boolean success) { + super(cmd, details, success); vncPort = null; } diff --git a/api/src/com/cloud/agent/api/StopCommand.java b/api/src/com/cloud/agent/api/StopCommand.java index 734da8415ec..176a7fb86ee 100755 --- a/api/src/com/cloud/agent/api/StopCommand.java +++ b/api/src/com/cloud/agent/api/StopCommand.java @@ -23,7 +23,6 @@ public class StopCommand extends RebootCommand { private boolean isProxy=false; private String urlPort=null; private String publicConsoleProxyIpAddress=null; - private String privateRouterIpAddress=null; protected StopCommand() { } @@ -45,12 +44,6 @@ public class StopCommand extends RebootCommand { this.vnet = vnet; } - public StopCommand(VirtualMachine vm, String vmName, String vnet, String privateRouterIpAddress) { - super(vmName); - this.vnet = vnet; - this.privateRouterIpAddress = privateRouterIpAddress; - } - public StopCommand(String vmName) { super(vmName); } @@ -76,7 +69,4 @@ public class StopCommand extends RebootCommand { return this.publicConsoleProxyIpAddress; } - public String getPrivateRouterIpAddress() { - return privateRouterIpAddress; - } } diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java index c48b13f66bb..c5cb586e528 100755 --- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java +++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java @@ -716,7 +716,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { vm = OvmVm.getDetails(_conn, vmName); } catch (XmlRpcException e) { s_logger.debug("Unable to get details of vm: " + vmName + ", treating it as stopped", e); - return new StopAnswer(cmd, "success", 0, 0L, 0L); + return new StopAnswer(cmd, "success", 0, true); } deleteAllNetworkRulesForVm(vmName); @@ -724,10 +724,10 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { cleanup(vm); state = State.Stopped; - return new StopAnswer(cmd, "success", 0, 0L, 0L); + return new StopAnswer(cmd, "success", 0, true); } catch (Exception e) { s_logger.debug("Stop " + vmName + "failed", e); - return new StopAnswer(cmd, e.getMessage()); + return new StopAnswer(cmd, e.getMessage(), false); } finally { synchronized(_vms) { if (state != null) { @@ -749,10 +749,10 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { try { Map res = OvmVm.reboot(_conn, vmName); Integer vncPort = Integer.parseInt(res.get("vncPort")); - return new RebootAnswer(cmd, null, null, null, vncPort); + return new RebootAnswer(cmd, null, vncPort); } catch (Exception e) { s_logger.debug("Reboot " + vmName + " failed", e); - return new RebootAnswer(cmd, e.getMessage()); + return new RebootAnswer(cmd, e.getMessage(), false); } finally { synchronized(_vms) { _vms.put(cmd.getVmName(), State.Running); 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 208cbbea8ce..e837dbd15e8 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 @@ -2027,16 +2027,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, "0"); if (getVmState(vmMo) != State.Stopped) { - Long bytesSent = 0L; - Long bytesRcvd = 0L; - - if (VirtualMachineName.isValidRouterName(cmd.getVmName())) { - if (cmd.getPrivateRouterIpAddress() != null) { - long[] stats = getNetworkStats(cmd.getPrivateRouterIpAddress()); - bytesSent = stats[0]; - bytesRcvd = stats[1]; - } - } // before we stop VM, remove all possible snapshots on the VM to let // disk chain be collapsed @@ -2044,11 +2034,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmMo.removeAllSnapshots(); if (vmMo.safePowerOff(_shutdown_waitMs)) { state = State.Stopped; - return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", 0, bytesSent, bytesRcvd); + return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", 0, true); } else { String msg = "Have problem in powering off VM " + cmd.getVmName() + ", let the process continue"; s_logger.warn(msg); - return new StopAnswer(cmd, msg, 0, 0L, 0L); + return new StopAnswer(cmd, msg, 0, true); } } else { state = State.Stopped; @@ -2056,7 +2046,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String msg = "VM " + cmd.getVmName() + " is already in stopped state"; s_logger.info(msg); - return new StopAnswer(cmd, msg, 0, 0L, 0L); + return new StopAnswer(cmd, msg, 0, true); } finally { synchronized (_vms) { _vms.put(cmd.getVmName(), state); @@ -2069,7 +2059,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String msg = "VM " + cmd.getVmName() + " is no longer in vSphere"; s_logger.info(msg); - return new StopAnswer(cmd, msg, 0, 0L, 0L); + return new StopAnswer(cmd, msg, 0, true); } } catch (Exception e) { if (e instanceof RemoteException) { @@ -2079,7 +2069,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String msg = "StopCommand failed due to " + VmwareHelper.getExceptionMessage(e); s_logger.error(msg); - return new StopAnswer(cmd, msg); + return new StopAnswer(cmd, msg, false); } } @@ -2088,17 +2078,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.info("Executing resource RebootRouterCommand: " + _gson.toJson(cmd)); } - Long bytesSent = 0L; - Long bytesRcvd = 0L; - if (VirtualMachineName.isValidRouterName(cmd.getVmName())) { - long[] stats = getNetworkStats(cmd.getPrivateIpAddress()); - bytesSent = stats[0]; - bytesRcvd = stats[1]; - } - RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); - answer.setBytesSent(bytesSent); - answer.setBytesReceived(bytesRcvd); if (answer.getResult()) { String connectResult = connect(cmd.getVmName(), cmd.getPrivateIpAddress()); @@ -2124,7 +2104,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (vmMo != null) { try { vmMo.rebootGuest(); - return new RebootAnswer(cmd, "reboot succeeded", null, null); + return new RebootAnswer(cmd, "reboot succeeded", true); } catch(ToolsUnavailable e) { s_logger.warn("VMware tools is not installed at guest OS, we will perform hard reset for reboot"); } catch(Exception e) { @@ -2133,16 +2113,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa // continue to try with hard-reset if (vmMo.reset()) { - return new RebootAnswer(cmd, "reboot succeeded", null, null); + return new RebootAnswer(cmd, "reboot succeeded", true); } String msg = "Reboot failed in vSphere. vm: " + cmd.getVmName(); s_logger.warn(msg); - return new RebootAnswer(cmd, msg); + return new RebootAnswer(cmd, msg, false); } else { String msg = "Unable to find the VM in vSphere to reboot. vm: " + cmd.getVmName(); s_logger.warn(msg); - return new RebootAnswer(cmd, msg); + return new RebootAnswer(cmd, msg, false); } } catch (Exception e) { if (e instanceof RemoteException) { @@ -2152,7 +2132,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String msg = "RebootCommand failed due to " + VmwareHelper.getExceptionMessage(e); s_logger.error(msg); - return new RebootAnswer(cmd, msg); + return new RebootAnswer(cmd, msg, false); } } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index c81d4613509..19cb7961819 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -201,7 +201,6 @@ import com.cloud.utils.net.NetUtils; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.VirtualMachineName; import com.trilead.ssh2.SCPClient; import com.xensource.xenapi.Bond; import com.xensource.xenapi.Connection; @@ -2823,10 +2822,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vms = VM.getByNameLabel(conn, cmd.getVmName()); } catch (XenAPIException e0) { s_logger.debug("getByNameLabel failed " + e0.toString()); - return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString()); + return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString(), false); } catch (Exception e0) { s_logger.debug("getByNameLabel failed " + e0.getMessage()); - return new RebootAnswer(cmd, "getByNameLabel failed"); + return new RebootAnswer(cmd, "getByNameLabel failed", false); } for (VM vm : vms) { try { @@ -2834,10 +2833,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } catch (Exception e) { String msg = e.toString(); s_logger.warn(msg, e); - return new RebootAnswer(cmd, msg); + return new RebootAnswer(cmd, msg, false); } } - return new RebootAnswer(cmd, "reboot succeeded", null, null); + return new RebootAnswer(cmd, "reboot succeeded", true); } finally { synchronized (_cluster.intern()) { s_vms.put(_cluster, _name, cmd.getVmName(), State.Running); @@ -2848,16 +2847,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected Answer execute(RebootRouterCommand cmd) { Connection conn = getConnection(); - Long bytesSent = 0L; - Long bytesRcvd = 0L; - if (VirtualMachineName.isValidRouterName(cmd.getVmName())) { - long[] stats = getNetworkStats(conn, cmd.getPrivateIpAddress()); - bytesSent = stats[0]; - bytesRcvd = stats[1]; - } RebootAnswer answer = execute((RebootCommand) cmd); - answer.setBytesSent(bytesSent); - answer.setBytesReceived(bytesRcvd); if (answer.getResult()) { String cnct = connect(conn, cmd.getVmName(), cmd.getPrivateIpAddress()); networkUsage(conn, cmd.getPrivateIpAddress(), "create", null); @@ -3320,23 +3310,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.info("VM does not exist on XenServer" + _host.uuid); s_vms.remove(_cluster, _name, vmName); } - return new StopAnswer(cmd, "VM does not exist", 0 , 0L, 0L); + return new StopAnswer(cmd, "VM does not exist", 0 , true); } - Long bytesSent = 0L; - Long bytesRcvd = 0L; for (VM vm : vms) { VM.Record vmr = vm.getRecord(conn); if (vmr.isControlDomain) { String msg = "Tring to Shutdown control domain"; s_logger.warn(msg); - return new StopAnswer(cmd, msg); + return new StopAnswer(cmd, msg, false); } if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) { String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.uuid + " but host:" + vmr.residentOn.getUuid(conn); s_logger.warn(msg); - return new StopAnswer(cmd, msg); + return new StopAnswer(cmd, msg, false); } State state = s_vms.getState(_cluster, vmName); @@ -3350,13 +3338,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (vmr.powerState == VmPowerState.RUNNING) { /* when stop a vm, set affinity to current xenserver */ vm.setAffinity(conn, vm.getResidentOn(conn)); - if (VirtualMachineName.isValidRouterName(vmName)) { - if (cmd.getPrivateRouterIpAddress() != null) { - long[] stats = getNetworkStats(conn, cmd.getPrivateRouterIpAddress()); - bytesSent = stats[0]; - bytesRcvd = stats[1]; - } - } + if (_canBridgeFirewall) { String result = callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", cmd .getVmName()); @@ -3371,7 +3353,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } catch (Exception e) { String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + cmd.getVmName() + " due to " + e.toString(); s_logger.debug(msg); - return new StopAnswer(cmd, msg); + return new StopAnswer(cmd, msg, false); } finally { try { @@ -3396,7 +3378,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe disableVlanNetwork(conn, network); } } - return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, bytesSent, bytesRcvd); + return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, true); } } catch (XenAPIException e) { String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString(); @@ -3416,16 +3398,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } catch (XenAPIException e) { String msg = "Stop Vm " + vmName + " fail due to " + e.toString(); s_logger.warn(msg, e); - return new StopAnswer(cmd, msg); + return new StopAnswer(cmd, msg, false); } catch (XmlRpcException e) { String msg = "Stop Vm " + vmName + " fail due to " + e.getMessage(); s_logger.warn(msg, e); - return new StopAnswer(cmd, msg); + return new StopAnswer(cmd, msg, false); } catch (Exception e) { s_logger.warn("Unable to stop " + vmName + " due to ", e); return new StopAnswer(cmd, e); } - return new StopAnswer(cmd, "Stop VM failed"); + return new StopAnswer(cmd, "Stop VM failed", false); } private List getVdis(Connection conn, VM vm) { diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 8d1963d303a..272c3575d1f 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -996,4 +996,9 @@ public class ElasticLoadBalancerManagerImpl implements // TODO Auto-generated method stub return false; } + + @Override + public void prepareStop(VirtualMachineProfile profile) { + } + } diff --git a/server/src/com/cloud/baremetal/BareMetalResourceBase.java b/server/src/com/cloud/baremetal/BareMetalResourceBase.java index 4835bd4efb6..24f80026bbf 100755 --- a/server/src/com/cloud/baremetal/BareMetalResourceBase.java +++ b/server/src/com/cloud/baremetal/BareMetalResourceBase.java @@ -428,10 +428,10 @@ public class BareMetalResourceBase implements ServerResource { protected RebootAnswer execute(final RebootCommand cmd) { if (!doScript(_rebootCommand)) { - return new RebootAnswer(cmd, "IPMI reboot failed"); + return new RebootAnswer(cmd, "IPMI reboot failed", false); } - return new RebootAnswer(cmd, "reboot succeeded", null, null); + return new RebootAnswer(cmd, "reboot succeeded", true); } protected StopAnswer execute(final StopCommand cmd) { @@ -466,7 +466,7 @@ public class BareMetalResourceBase implements ServerResource { count++; } - return success ? new StopAnswer(cmd, "Success", null, Long.valueOf(0), Long.valueOf(0)) : new StopAnswer(cmd, "IPMI power off failed"); + return success ? new StopAnswer(cmd, "Success", null, true) : new StopAnswer(cmd, "IPMI power off failed", false); } protected StartAnswer execute(StartCommand cmd) { diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index 6d20fb2fc31..a7e457c02d4 100755 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -353,4 +353,8 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu // TODO Auto-generated method stub return false; } + + @Override + public void prepareStop(VirtualMachineProfile profile) { + } } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index ec4f685f3a7..71013751234 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -2014,4 +2014,8 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx // TODO Auto-generated method stub return false; } + + @Override + public void prepareStop(VirtualMachineProfile profile) { + } } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 766c7690ee8..82f7231e172 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -506,34 +506,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian txn.start(); final UserStatisticsVO userStats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterIdToDeployIn(), router.getNetworkId(), null, router.getId(), router.getType().toString()); if (userStats != null) { - final RebootAnswer sa = (RebootAnswer) answer; - final Long received = sa.getBytesReceived(); - long netBytes = 0; - if (received != null) { - if (received.longValue() >= userStats.getCurrentBytesReceived()) { - netBytes = received.longValue(); - } else { - netBytes = userStats.getCurrentBytesReceived() + received; - } - } else { - netBytes = userStats.getCurrentBytesReceived(); - } + final long currentBytesRcvd = userStats.getCurrentBytesReceived(); userStats.setCurrentBytesReceived(0); - userStats.setNetBytesReceived(userStats.getNetBytesReceived() + netBytes); + userStats.setNetBytesReceived(userStats.getNetBytesReceived() + currentBytesRcvd); - final Long sent = sa.getBytesSent(); - - if (sent != null) { - if (sent.longValue() >= userStats.getCurrentBytesSent()) { - netBytes = sent.longValue(); - } else { - netBytes = userStats.getCurrentBytesSent() + sent; - } - } else { - netBytes = userStats.getCurrentBytesSent(); - } - userStats.setNetBytesSent(userStats.getNetBytesSent() + netBytes); + final long currentBytesSent = userStats.getCurrentBytesSent(); userStats.setCurrentBytesSent(0); + userStats.setNetBytesSent(userStats.getNetBytesSent() + currentBytesSent); _userStatsDao.update(userStats.getId(), userStats); s_logger.debug("Successfully updated user statistics as a part of domR " + router + " reboot/stop"); } else { @@ -542,7 +521,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian txn.commit(); } catch (final Exception e) { txn.rollback(); - throw new CloudRuntimeException("Problem getting stats after reboot/stop ", e); + throw new CloudRuntimeException("Problem updating stats after reboot/stop ", e); } } @@ -2985,4 +2964,99 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian return false; } + + @Override + public void prepareStop(VirtualMachineProfile profile){ + //Collect network usage before stopping Vm + VMInstanceVO vm = profile.getVirtualMachine(); + DomainRouterVO router = _routerDao.findById(vm.getId()); + if(router == null){ + return; + } + /*String privateIP = router.getPrivateIpAddress(); + + if (privateIP != null) { + List routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId()); + + for (Long guestNtwkId : routerGuestNtwkIds) { + boolean forVpc = router.getVpcId() != null; + Network guestNtwk = _networkMgr.getNetwork(guestNtwkId); + Nic guestNic = _nicDao.findByInstanceIdAndNetworkId(guestNtwk.getId(), router.getId()); + NicProfile guestNicProfile = new NicProfile(guestNic, guestNtwk, guestNic.getBroadcastUri(), + guestNic.getIsolationUri(), _networkMgr.getNetworkRate(guestNtwk.getId(), router.getId()), + _networkMgr.isSecurityGroupSupportedInNetwork(guestNtwk), + _networkMgr.getNetworkTag(router.getHypervisorType(), guestNtwk)); + final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), + forVpc, _itMgr.toNicTO(guestNicProfile, router.getHypervisorType())); + UserStatisticsVO previousStats = _statsDao.findBy(router.getAccountId(), + router.getDataCenterIdToDeployIn(), guestNtwkId, null, router.getId(), router.getType().toString()); + NetworkUsageAnswer answer = null; + try { + answer = (NetworkUsageAnswer) _agentMgr.easySend(router.getHostId(), usageCmd); + } catch (Exception e) { + s_logger.warn("Error while collecting network stats from router: "+router.getInstanceName()+" from host: "+router.getHostId(), e); + continue; + } + + if (answer != null) { + if (!answer.getResult()) { + s_logger.warn("Error while collecting network stats from router: "+router.getInstanceName()+" from host: "+router.getHostId() + "; details: " + answer.getDetails()); + continue; + } + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + if ((answer.getBytesReceived() == 0) && (answer.getBytesSent() == 0)) { + s_logger.debug("Recieved and Sent bytes are both 0. Not updating user_statistics"); + continue; + } + txn.start(); + UserStatisticsVO stats = _statsDao.lock(router.getAccountId(), + router.getDataCenterIdToDeployIn(), guestNtwkId, null, router.getId(), router.getType().toString()); + if (stats == null) { + s_logger.warn("unable to find stats for account: " + router.getAccountId()); + continue; + } + + if(previousStats != null + && ((previousStats.getCurrentBytesReceived() != stats.getCurrentBytesReceived()) + || (previousStats.getCurrentBytesSent() != stats.getCurrentBytesSent()))){ + s_logger.debug("Router stats changed from the time NetworkUsageCommand was sent. " + + "Ignoring current answer. Router: "+answer.getRouterName()+" Rcvd: " + + answer.getBytesReceived()+ "Sent: " +answer.getBytesSent()); + continue; + } + + if (stats.getCurrentBytesReceived() > answer.getBytesReceived()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Received # of bytes that's less than the last one. " + + "Assuming something went wrong and persisting it. Router: " + + answer.getRouterName()+" Reported: " + answer.getBytesReceived() + + " Stored: " + stats.getCurrentBytesReceived()); + } + stats.setNetBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived()); + } + stats.setCurrentBytesReceived(answer.getBytesReceived()); + if (stats.getCurrentBytesSent() > answer.getBytesSent()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Received # of bytes that's less than the last one. " + + "Assuming something went wrong and persisting it. Router: " + + answer.getRouterName()+" Reported: " + answer.getBytesSent() + + " Stored: " + stats.getCurrentBytesSent()); + } + stats.setNetBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent()); + } + stats.setCurrentBytesSent(answer.getBytesSent()); + _statsDao.update(stats.getId(), stats); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.warn("Unable to update user statistics for account: " + router.getAccountId() + + " Rx: " + answer.getBytesReceived() + "; Tx: " + answer.getBytesSent()); + } finally { + txn.close(); + } + } + } + }*/ + } } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 1121bb19f61..3ef055d74c0 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -1457,5 +1457,10 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V Commands cmds, ReservationContext context) { // TODO Auto-generated method stub return false; + } + + @Override + public void prepareStop(VirtualMachineProfile profile) { + } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 649e215acf0..b221ef1eac9 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -3630,5 +3630,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager return vm; } + @Override + public void prepareStop(VirtualMachineProfile profile) { + } } diff --git a/server/src/com/cloud/vm/VirtualMachineGuru.java b/server/src/com/cloud/vm/VirtualMachineGuru.java index b92982c7b31..26c3944394c 100644 --- a/server/src/com/cloud/vm/VirtualMachineGuru.java +++ b/server/src/com/cloud/vm/VirtualMachineGuru.java @@ -74,4 +74,11 @@ public interface VirtualMachineGuru { * @return id if the handler works for this vm and can parse id. null if not. */ Long convertToId(String vmName); + + /** + * Prepare Vm for Stop + * @param profile + * @return + */ + void prepareStop(VirtualMachineProfile profile); } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index ac8fd2ab46b..3f7cab914a9 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1070,11 +1070,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene if (vm.getState() != State.Stopping) { throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState()); } - String routerPrivateIp = null; - if (vm.getType() == VirtualMachine.Type.DomainRouter) { - routerPrivateIp = vm.getPrivateIpAddress(); - } - StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null, routerPrivateIp); + + vmGuru.prepareStop(profile); + + StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null); boolean stopped = false; StopAnswer answer = null; try { From 2943dc22d75ba5d8832f972eb049370f2e2d1060 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Fri, 27 Jul 2012 15:07:36 -0700 Subject: [PATCH 12/66] CS-15717: fail to delete the network when corresponding network elements fail to be destroyed --- server/src/com/cloud/network/NetworkManagerImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index c96ea52b299..83acc9b9c35 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -3215,7 +3215,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.debug("Sending destroy to " + element); } - element.destroy(network); + if (!element.destroy(network)) { + success = false; + s_logger.warn("Unable to complete destroy of the network: failed to destroy network element " + element.getName()); + } } catch (ResourceUnavailableException e) { s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e); success = false; @@ -3225,7 +3228,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } catch (Exception e) { s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e); success = false; - } + } } } From 25e0cc9d7569008f7c592e33b97c8d8568c1a8eb Mon Sep 17 00:00:00 2001 From: "chip.childers@gmail.com" Date: Fri, 27 Jul 2012 23:35:01 -0400 Subject: [PATCH 13/66] Checkpoint commit - work in progress. Attempting to provide devcloud base box build process via veewee and puppet provisining via Vagrant. --- .../{vagrant => basebuild}/Vagrantfile | 29 ++--------- .../puppet-devcloudinitial/Modulefile | 0 .../puppet-devcloudinitial/files/grub | 2 +- .../puppet-devcloudinitial/files/interfaces | 0 .../puppet-devcloudinitial/files/network.conf | 0 .../puppet-devcloudinitial/files/xen-defaults | 0 .../puppet-devcloudinitial/files/xend | 0 .../puppet-devcloudinitial/init.pp | 0 .../puppet-devcloudinitial/manifests/init.pp | 10 ++-- tools/devcloud/devcloudbox/Vagrantfile | 51 +++++++++++++++++++ .../devcloudbox/puppet-devcloud/Modulefile | 8 +++ .../puppet-devcloud/files/iptables.save | 17 +++++++ .../devcloudbox/puppet-devcloud/init.pp | 1 + .../puppet-devcloud/manifests/init.pp | 32 ++++++++++++ tools/devcloud/puppet/README | 12 ----- tools/devcloud/ubuntu_install/README | 1 - tools/devcloud/vagrant/vagrant.pp | 43 ---------------- tools/devcloud/veewee/postinstall.sh | 42 +++++++++++++++ 18 files changed, 161 insertions(+), 87 deletions(-) rename tools/devcloud/{vagrant => basebuild}/Vagrantfile (66%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/Modulefile (100%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/files/grub (98%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/files/interfaces (100%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/files/network.conf (100%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/files/xen-defaults (100%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/files/xend (100%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/init.pp (100%) rename tools/devcloud/{puppet => basebuild}/puppet-devcloudinitial/manifests/init.pp (89%) create mode 100644 tools/devcloud/devcloudbox/Vagrantfile create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/Modulefile create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/files/iptables.save create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/init.pp create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp delete mode 100644 tools/devcloud/puppet/README delete mode 100644 tools/devcloud/ubuntu_install/README delete mode 100644 tools/devcloud/vagrant/vagrant.pp create mode 100644 tools/devcloud/veewee/postinstall.sh diff --git a/tools/devcloud/vagrant/Vagrantfile b/tools/devcloud/basebuild/Vagrantfile similarity index 66% rename from tools/devcloud/vagrant/Vagrantfile rename to tools/devcloud/basebuild/Vagrantfile index d2a9c9926c7..eee8127cd2f 100644 --- a/tools/devcloud/vagrant/Vagrantfile +++ b/tools/devcloud/basebuild/Vagrantfile @@ -19,13 +19,15 @@ # under the License. Vagrant::Config.run do |config| - config.vm.box = "devcloudbase-ubuntu-12-04-64bit" + config.vm.box = "devcloud" # TODO: Get a URL to host the base image # config.vm.box_url = "http://domain.com/path/to/above.box" + config.vm.guest = :xen + config.ssh.username = "devcloud" # Uncomment this line to enable the console for debugging the # build process. - #config.vm.boot_mode = :gui + config.vm.boot_mode = :gui # Setup port forwarding config.vm.forward_port 22, 2222 @@ -46,27 +48,4 @@ Vagrant::Config.run do |config| puppet.module_path = "puppet-devcloudinitial" end - # Enable provisioning with Puppet stand alone. Puppet manifests - # are contained in a directory path relative to this Vagrantfile. - # You will need to create the manifests directory and a manifest in - # the file my_box.pp in the manifests_path directory. - # - # An example Puppet manifest to provision the message of the day: - # - # # group { "puppet": - # # ensure => "present", - # # } - # # - # # File { owner => 0, group => 0, mode => 0644 } - # # - # # file { '/etc/motd': - # # content => "Welcome to your Vagrant-built virtual machine! - # # Managed by Puppet.\n" - # # } - # - # config.vm.provision :puppet do |puppet| - # puppet.manifests_path = "manifests" - # puppet.manifest_file = "my_box.pp" - # end - end diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/Modulefile b/tools/devcloud/basebuild/puppet-devcloudinitial/Modulefile similarity index 100% rename from tools/devcloud/puppet/puppet-devcloudinitial/Modulefile rename to tools/devcloud/basebuild/puppet-devcloudinitial/Modulefile diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/files/grub b/tools/devcloud/basebuild/puppet-devcloudinitial/files/grub similarity index 98% rename from tools/devcloud/puppet/puppet-devcloudinitial/files/grub rename to tools/devcloud/basebuild/puppet-devcloudinitial/files/grub index 88138000e20..34613daf474 100644 --- a/tools/devcloud/puppet/puppet-devcloudinitial/files/grub +++ b/tools/devcloud/basebuild/puppet-devcloudinitial/files/grub @@ -3,7 +3,7 @@ # For full documentation of the options in this file, see: # info -f grub -n 'Simple configuration' -GRUB_DEFAULT=0 +GRUB_DEFAULT=2 #GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=2 diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/files/interfaces b/tools/devcloud/basebuild/puppet-devcloudinitial/files/interfaces similarity index 100% rename from tools/devcloud/puppet/puppet-devcloudinitial/files/interfaces rename to tools/devcloud/basebuild/puppet-devcloudinitial/files/interfaces diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/files/network.conf b/tools/devcloud/basebuild/puppet-devcloudinitial/files/network.conf similarity index 100% rename from tools/devcloud/puppet/puppet-devcloudinitial/files/network.conf rename to tools/devcloud/basebuild/puppet-devcloudinitial/files/network.conf diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/files/xen-defaults b/tools/devcloud/basebuild/puppet-devcloudinitial/files/xen-defaults similarity index 100% rename from tools/devcloud/puppet/puppet-devcloudinitial/files/xen-defaults rename to tools/devcloud/basebuild/puppet-devcloudinitial/files/xen-defaults diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/files/xend b/tools/devcloud/basebuild/puppet-devcloudinitial/files/xend similarity index 100% rename from tools/devcloud/puppet/puppet-devcloudinitial/files/xend rename to tools/devcloud/basebuild/puppet-devcloudinitial/files/xend diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/init.pp b/tools/devcloud/basebuild/puppet-devcloudinitial/init.pp similarity index 100% rename from tools/devcloud/puppet/puppet-devcloudinitial/init.pp rename to tools/devcloud/basebuild/puppet-devcloudinitial/init.pp diff --git a/tools/devcloud/puppet/puppet-devcloudinitial/manifests/init.pp b/tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp similarity index 89% rename from tools/devcloud/puppet/puppet-devcloudinitial/manifests/init.pp rename to tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp index 79988c6934b..8a0a9d011dc 100644 --- a/tools/devcloud/puppet/puppet-devcloudinitial/manifests/init.pp +++ b/tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp @@ -4,12 +4,12 @@ class puppet-devcloudinitial { ensure => latest, } - package { 'xen-hypervisor-4.1-amd64': + package { 'xen-hypervisor-4.1-i386': ensure => latest, } package { 'xcp-xapi': - require => Package['xen-hypervisor-4.1-amd64'], + require => Package['xen-hypervisor-4.1-i386'], ensure => latest, } @@ -38,7 +38,7 @@ class puppet-devcloudinitial { } file { '/etc/default/grub': - require => Package['xen-hypervisor-4.1-amd64'], + require => Package['xen-hypervisor-4.1-i386'], ensure => 'file', source => 'puppet:///modules/puppet-devcloudinitial/grub', group => '0', @@ -53,7 +53,7 @@ class puppet-devcloudinitial { } file { '/usr/share/qemu': - require => Package['xen-hypervisor-4.1-amd64'], + require => Package['xen-hypervisor-4.1-i386'], ensure => 'directory', group => '0', mode => '755', @@ -78,7 +78,7 @@ class puppet-devcloudinitial { } file { '/etc/default/xen': - require => Package['xen-hypervisor-4.1-amd64'], + require => Package['xen-hypervisor-4.1-i386'], ensure => 'file', source => 'puppet:///modules/puppet-devcloudinitial/xen-defaults', group => '0', diff --git a/tools/devcloud/devcloudbox/Vagrantfile b/tools/devcloud/devcloudbox/Vagrantfile new file mode 100644 index 00000000000..6138926bab9 --- /dev/null +++ b/tools/devcloud/devcloudbox/Vagrantfile @@ -0,0 +1,51 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +Vagrant::Config.run do |config| + config.vm.box = "devcloud" + # TODO: Get a URL to host the base image + # config.vm.box_url = "http://domain.com/path/to/above.box" + config.vm.guest = :xen + config.ssh.username = "devcloud" + + # Uncomment this line to enable the console for debugging the + # build process. + config.vm.boot_mode = :gui + + # Setup port forwarding + config.vm.forward_port 22, 2222 + config.vm.forward_port 8080, 8080 + config.vm.forward_port 8443, 8443 + config.vm.forward_port 5901, 5901 + config.vm.forward_port 8787, 8787 + config.vm.forward_port 8250, 8250 + + # Ensure the VM has the right virtual resources + #config.vm. + +# config.vm.provision :puppet do |puppet| +# puppet.manifests_path = "puppet-devcloud" +# puppet.manifest_file = "init.pp" +# puppet.with_ssh = true +# puppet.pp_path = "/etc/puppet" +# puppet.module_path = "puppet-devcloud" +# end + +end diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/Modulefile b/tools/devcloud/devcloudbox/puppet-devcloud/Modulefile new file mode 100644 index 00000000000..7da4c4cf590 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/Modulefile @@ -0,0 +1,8 @@ +name 'puppet-devcloud' +version '0.0.1' +source '' +author 'Apache Software Foundation' +license 'Apache 2.0' +summary 'CloudStack DevCloud configuration module' +description 'Devcloud setup module.' +project_page 'http://cloudstack.org' diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/files/iptables.save b/tools/devcloud/devcloudbox/puppet-devcloud/files/iptables.save new file mode 100644 index 00000000000..c556398ca15 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/files/iptables.save @@ -0,0 +1,17 @@ +# Generated by iptables-save v1.4.12 on Sat Jul 28 03:18:44 2012 +*mangle +:PREROUTING ACCEPT [397:23804] +:INPUT ACCEPT [397:23804] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [238:22820] +:POSTROUTING ACCEPT [238:22820] +-A POSTROUTING -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill +COMMIT +# Completed on Sat Jul 28 03:18:44 2012 +# Generated by iptables-save v1.4.12 on Sat Jul 28 03:18:44 2012 +*filter +:INPUT ACCEPT [453:27164] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [273:26476] +COMMIT +# Completed on Sat Jul 28 03:18:44 2012 diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/init.pp b/tools/devcloud/devcloudbox/puppet-devcloud/init.pp new file mode 100644 index 00000000000..c3922e39d30 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/init.pp @@ -0,0 +1 @@ +include puppet-devcloud diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp new file mode 100644 index 00000000000..b5d75b16425 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp @@ -0,0 +1,32 @@ +class puppet-devcloud { + + package { 'ebtables': + ensure => latest, + } + + service { 'ebtables': + require => Package['ebtables'], + ensure => 'running', + enable => 'true', + } + + package { 'iptables': + ensure => latest, + } + + file { '/etc/iptables.save': + require => Package['iptables'], + ensure => 'file', + source => 'puppet:///modules/puppet-devcloud/iptables.save', + group => '0', + mode => '644', + owner => '0', + } + + exec { "mac=`ifconfig xenbr0 |grep HWaddr |awk '{print $5}'`; /sbin/ebtables -I FORWARD -d ! $mac -i eth0 -p IPV4 --ip-prot udp --ip-dport 67:68 -j DROP": + subscribe => Package['ebtables'], + refreshonly => true, + cwd => '/', + } + +} diff --git a/tools/devcloud/puppet/README b/tools/devcloud/puppet/README deleted file mode 100644 index f15f440abd1..00000000000 --- a/tools/devcloud/puppet/README +++ /dev/null @@ -1,12 +0,0 @@ -To use: - -Preconfiguration phase - -- [setup your box in vagrant and place the contents of tools/devcloud/puppet into the box's folder] -- vagrant up; vagrant ssh -- sudo bash -- ln -s /vagrant/puppet-devcloudinitial /etc/puppet/modules/puppet-devcloudinitial -- cd /vagrant -- puppet apply --fsconfig fileserver.conf --debug --verbose -e "include puppet-devcloudinitial" - -Postconfiguration phase - -TODO diff --git a/tools/devcloud/ubuntu_install/README b/tools/devcloud/ubuntu_install/README deleted file mode 100644 index 7432dbc3297..00000000000 --- a/tools/devcloud/ubuntu_install/README +++ /dev/null @@ -1 +0,0 @@ -Nothing in this directory yet, but it will contain the scripts and preconfiguration files to build the basic Ubuntu 12.04 server used in devcloud. diff --git a/tools/devcloud/vagrant/vagrant.pp b/tools/devcloud/vagrant/vagrant.pp deleted file mode 100644 index 1be66262876..00000000000 --- a/tools/devcloud/vagrant/vagrant.pp +++ /dev/null @@ -1,43 +0,0 @@ -group { 'vagranttest': - ensure => 'present', - gid => '5000', -} - -group { 'admin': - ensure => 'present', - gid => '1002', -} - -user { 'vagranttest': - ensure => 'present', - comment => 'vagrant,,,', - gid => '5000', - groups => ['adm', 'cdrom', 'dip', 'plugdev', 'lpadmin', 'sambashare', 'admin'], - home => '/home/vagranttest', - shell => '/bin/bash', - uid => '5000', -} - -file { '/home/vagranttest': - ensure => 'directory', - group => '1002', - mode => '755', - owner => '5000', -} - -file { '/home/vagranttest/.ssh': - ensure => 'directory', - group => '1002', - mode => '775', - owner => '5000', -} - -$auth_key = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" - -file { '/home/vagranttest/.ssh/authorized_keys': - ensure => 'file', - content => $auth_key, - group => '1002', - mode => '664', - owner => '5000', -} diff --git a/tools/devcloud/veewee/postinstall.sh b/tools/devcloud/veewee/postinstall.sh new file mode 100644 index 00000000000..a650501fb61 --- /dev/null +++ b/tools/devcloud/veewee/postinstall.sh @@ -0,0 +1,42 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +apt-get -y update +apt-get -y upgrade +apt-get -y install vim +apt-get -y install ruby +apt-get -y install rubygems +apt-get -y install puppet +apt-get clean + +# Setup sudo to allow no-password sudo for "admin" +groupadd -r admin +usermod -a -G admin devcloud +sed -i -e '/Defaults\s\+env_reset/a Defaults\texempt_group=admin' /etc/sudoers +sed -i -e 's/%admin ALL=(ALL) ALL/%admin ALL=NOPASSWD:ALL/g' /etc/sudoers + +mkdir /home/devcloud/.ssh +chmod 700 /home/devcloud/.ssh +cd /home/devcloud/.ssh +wget --no-check-certificate 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub' -O authorized_keys +chmod 600 /home/devcloud/.ssh/authorized_keys +chown -R devcloud /home/devcloud/.ssh + +# Zero out the free space to save space in the final image: +dd if=/dev/zero of=/EMPTY bs=1M +rm -f /EMPTY + From 3d866c4bbb8fec8e9580278429a2d94b31ec9570 Mon Sep 17 00:00:00 2001 From: Joe Brockmeier Date: Sat, 28 Jul 2012 18:02:13 -0400 Subject: [PATCH 14/66] CS-15522 - fixing NFS settings to be less dangerous --- docs/runbook/en-US/Environment.xml | 49 ++++++++++++------------------ 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/docs/runbook/en-US/Environment.xml b/docs/runbook/en-US/Environment.xml index 9048e1aa0a2..99161d9cb69 100644 --- a/docs/runbook/en-US/Environment.xml +++ b/docs/runbook/en-US/Environment.xml @@ -68,6 +68,13 @@ ONBOOT="no" configure that file so that it specifies the IP address, netmask, etc., as shown in the following example: + + Hardware Addresses + You should not use the hardware address (aka MAC address) from our example + for your configuration. It is network interface specific, so you should keep the + address already provided in the HWADDR directive. + + DEVICE=eth0 HWADDR=52:54:00:B9:A6:C0 @@ -77,6 +84,8 @@ BOOTPROTO=none IPADDR=172.16.10.2 NETMASK=255.255.255.0 GATEWAY=172.16.10.1 +DNS1=8.8.8.8 +DNS2=8.8.4.4 IP Addressing @@ -89,26 +98,10 @@ GATEWAY=172.16.10.1 192.168.55.2 - - Hardware Addresses - You should not use the hardware address (aka MAC address) from our example - for your configuration. It is network interface specific, so you should keep the - address already provided in the HWADDR directive. - - Now that we have the configuration files properly set up, we need to run a few commands to start up the network # chkconfig network on # service network start - This should bring the network up successfully, but we now need to enable name resolution. - To do that we will edit /etc/resolv.conf. These instructions will add - one of the nameservers from Google, though you are free to add a local nameserver if you wish. - Your /etc/resolv.conf should modified to look like: - - -nameserver 8.8.8.8 - -
Hostname @@ -195,8 +188,6 @@ SELINUXTYPE=targeted # mkdir /primary # mkdir /secondary -# chmod 777 /primary -# chmod 777 /secondary CentOS 6.x releases use NFSv4 by default. NFSv4 requires that domain setting matches on all clients. In our case, the domain is cloud.priv, so ensure that the domain setting in /etc/idmapd.conf @@ -215,17 +206,17 @@ STATD_OUTGOING_PORT=2020 Edit the file /etc/sysconfig/iptables --A INPUT -m state --state NEW -p udp --dport 111 -j ACCEPT --A INPUT -m state --state NEW -p tcp --dport 111 -j ACCEPT --A INPUT -m state --state NEW -p tcp --dport 2049 -j ACCEPT --A INPUT -m state --state NEW -p tcp --dport 32803 -j ACCEPT --A INPUT -m state --state NEW -p udp --dport 32769 -j ACCEPT --A INPUT -m state --state NEW -p tcp --dport 892 -j ACCEPT --A INPUT -m state --state NEW -p udp --dport 892 -j ACCEPT --A INPUT -m state --state NEW -p tcp --dport 875 -j ACCEPT --A INPUT -m state --state NEW -p udp --dport 875 -j ACCEPT --A INPUT -m state --state NEW -p tcp --dport 662 -j ACCEPT --A INPUT -m state --state NEW -p udp --dport 662 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 111 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 111 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 2049 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 32803 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 32769 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 892 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 892 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 875 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 875 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 662 -j ACCEPT +-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 662 -j ACCEPT Now you can restart the iptables service with the following command: From 3313cc4a86461908421865ddb745c3d3d6169989 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 30 Jul 2012 08:38:50 +0200 Subject: [PATCH 15/66] rrq 5834: fix for broken attachVolume command --- server/src/com/cloud/vm/UserVmManagerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index b221ef1eac9..ab92c6b1585 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -344,7 +344,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager SecurityGroupVMMapDao _securityGroupVMMapDao; @Inject protected ItWorkDao _workDao; - VolumeHostDao _volumeHostDao; + @Inject + protected VolumeHostDao _volumeHostDao; @Inject ResourceTagDao _resourceTagDao; From 894407caa97ecd5b4f034de6b3b0e4deadd253e4 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 30 Jul 2012 08:46:56 +0200 Subject: [PATCH 16/66] rrq 5839: This table should not have a contraint on device and physical network id. This is dealt with in the code and by using the removed field. --- setup/db/create-schema.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index ae5f58160a4..dc9e7b0c748 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -2000,7 +2000,6 @@ CREATE TABLE `cloud`.`physical_network_service_providers` ( PRIMARY KEY (`id`), CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE, CONSTRAINT `uc_service_providers__uuid` UNIQUE (`uuid`), - UNIQUE KEY(`physical_network_id`, `provider_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`external_load_balancer_devices` ( From 7026822e205b99ce9e6ca2a011a1a4cb1a3717cc Mon Sep 17 00:00:00 2001 From: kishan Date: Mon, 30 Jul 2012 15:15:04 +0530 Subject: [PATCH 17/66] Fixed unittest build failure --- server/test/com/cloud/vm/MockUserVmManagerImpl.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java index 31065fe48a6..62db70cf203 100644 --- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java +++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java @@ -417,4 +417,10 @@ public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Mana return null; } + @Override + public void prepareStop(VirtualMachineProfile profile) { + // TODO Auto-generated method stub + + } + } From ba33a25c575897654fd8200b40596709be24a907 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 29 Jun 2012 13:24:57 +0530 Subject: [PATCH 18/66] Sandbox scripts for generating one host configuration - marvin/sandbox/advanced - marvin/sandbox/basic * supports generating configurations for cloudstack deployment with properties files. The format of the config, properties files and the process is explained in the tutorial: http://wiki.cloudstack.org/display/QA/Testing+with+python#Testingwithpython-DeploymentConfiguration --- .../marvin/sandbox/basic/setup.properties | 43 +++++++++++++++++++ tools/marvin/setup.py | 1 - 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tools/marvin/marvin/sandbox/basic/setup.properties diff --git a/tools/marvin/marvin/sandbox/basic/setup.properties b/tools/marvin/marvin/sandbox/basic/setup.properties new file mode 100644 index 00000000000..08cdb79abea --- /dev/null +++ b/tools/marvin/marvin/sandbox/basic/setup.properties @@ -0,0 +1,43 @@ +[globals] +#global settings in cloudstack +expunge.delay=60 +expunge.interval=60 +storage.cleanup.interval=300 +account.cleanup.interval=600 +expunge.workers=3 +workers=10 +use.user.concentrated.pod.allocation=false +vm.allocation.algorithm=random +vm.op.wait.interval=5 +guest.domain.suffix=sandbox.kvm +instance.name=QA +direct.agent.load.size=1000 +default.page.size=10000 +check.pod.cidrs=true +secstorage.allowed.internal.sites=10.147.28.0/24 +[environment] +dns=10.147.28.6 +mshost=localhost +mysql.host=localhost +mysql.cloud.user=cloud +mysql.cloud.passwd=cloud +[cloudstack] +#guest VLAN +zone.vlan=675-679 +#management network +private.gateway=10.147.29.1 +private.pod.startip=10.147.29.150 +private.pod.endip=10.147.29.159 +private.netmask=255.255.255.0 +#public network +public.gateway=10.147.31.1 +public.vlan.startip=10.147.31.150 +public.vlan.endip=10.147.31.159 +public.netmask=255.255.255.0 +#hypervisor host information +hypervisor=Simulator +host=sim +host.password=password +#storage pools +primary.pool=nfs://10.147.28.6:/export/home/sandbox/kamakura +secondary.pool=nfs://10.147.28.6:/export/home/sandbox/sstor diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index b2d6a40cd4b..211011d9885 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -36,7 +36,6 @@ setup(name="Marvin", packages=["marvin", "marvin.cloudstackAPI", "marvin.sandbox", "marvin.sandbox.advanced", "marvin.sandbox.basic", "marvin.pymysql", "marvin.pymysql.constants", "marvin.pymysql.tests"], license="LICENSE.txt", install_requires=[ - "Python>=2.7", "paramiko", "nose" ], From 85c5b5656d15f3e1efe69dabcbb4561f9f38f6e7 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 21 Jun 2012 09:26:06 +0530 Subject: [PATCH 19/66] adding unittest-xml-reporting as a dependency to marvin --- tools/marvin/setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index 211011d9885..c0e4af42d4c 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -37,6 +37,7 @@ setup(name="Marvin", license="LICENSE.txt", install_requires=[ "paramiko", - "nose" + "nose", + "unittest-xml-reporting" ], ) From 326655d8c682673f66f1ad3c94a3e57a90513514 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 28 Jun 2012 16:47:47 +0530 Subject: [PATCH 20/66] xml reports for TestCaseEngine Conflicts: tools/marvin/marvin/TestCaseExecuteEngine.py --- tools/marvin/marvin/TestCaseExecuteEngine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py index 79089ab41d7..07df5633c99 100644 --- a/tools/marvin/marvin/TestCaseExecuteEngine.py +++ b/tools/marvin/marvin/TestCaseExecuteEngine.py @@ -91,4 +91,4 @@ class TestCaseExecuteEngine(object): if self.format == "text": unittest.TextTestRunner(stream=self.testResultLogFile, verbosity=2).run(self.suite) elif self.format == "xml": - xmlrunner.XMLTestRunner(output=self.testResultLogFile, verbose=True).run(self.suite) + xmlrunner.XMLTestRunner(output='xml-reports', verbose=True).run(self.suite) From aa4ff878127f94ef125d8db1d32e988610209b80 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 29 Jun 2012 13:39:04 +0530 Subject: [PATCH 21/66] Post configuration tests to check - if system VMs are up and running - if built-in template is downloaded and ready to launch --- tools/marvin/marvin/testSetupSuccess.py | 64 +++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 tools/marvin/marvin/testSetupSuccess.py diff --git a/tools/marvin/marvin/testSetupSuccess.py b/tools/marvin/marvin/testSetupSuccess.py new file mode 100644 index 00000000000..ed167a17f20 --- /dev/null +++ b/tools/marvin/marvin/testSetupSuccess.py @@ -0,0 +1,64 @@ +import marvin +import unittest +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from time import sleep as delay + +class TestSetupSuccess(cloudstackTestCase): + """ + Test to verify if the cloudstack is ready to launch tests upon + 1. Verify that system VMs are up and running in all zones + 2. Verify that built-in templates are Ready in all zones + """ + @classmethod + def setUpClass(cls): + cls.apiClient = super(TestSetupSuccess, cls).getClsTestClient().getApiClient() + + zones = listZones.listZonesCmd() + cls.zones_list = cls.apiClient.listZones(zones) + cls.retry = 50 + + def test_systemVmReady(self): + """ + system VMs need to be ready and Running for each zone in cloudstack + """ + for z in self.zones_list: + retry = self.retry + while retry != 0: + self.debug("looking for system VMs in zone: %s, %s"%(z.id, z.name)) + sysvms = listSystemVms.listSystemVmsCmd() + sysvms.zoneid = z.id + sysvms.state = 'Running' + sysvms_list = self.apiClient.listSystemVms(sysvms) + if sysvms_list is not None and len(sysvms_list) == 2: + assert len(sysvms_list) == 2 + self.debug("found %d system VMs running {%s}"%(len(sysvms_list), sysvms_list)) + break + retry = retry - 1 + delay(60) #wait a minute for retry + self.assertNotEqual(retry, 0, "system VMs not Running in zone %s"%z.name) + + def test_templateBuiltInReady(self): + """ + built-in templates CentOS to be ready + """ + for z in self.zones_list: + retry = self.retry + while retry != 0: + self.debug("Looking for at least one ready builtin template") + templates = listTemplates.listTemplatesCmd() + templates.templatefilter = 'featured' + templates.listall = 'true' + templates_list = self.apiClient.listTemplates(templates) + if templates_list is not None: + builtins = [tmpl for tmpl in templates_list if tmpl.templatetype == 'BUILTIN' and tmpl.isready == True] + if len(builtins) > 0: + self.debug("Found %d builtins ready for use %s"%(len(builtins), builtins)) + break + retry = retry - 1 + delay(60) #wait a minute for retry + self.assertNotEqual(retry, 0, "builtIn templates not ready in zone %s"%z.name) + + @classmethod + def tearDownClass(cls): + pass From 9443734f1ddc4aa0cc38e4dad0e44325ffedcf84 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 6 Jul 2012 17:40:12 +0530 Subject: [PATCH 22/66] setup.properties for basic zone environments --- .../marvin/sandbox/basic/setup.properties | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tools/marvin/marvin/sandbox/basic/setup.properties b/tools/marvin/marvin/sandbox/basic/setup.properties index 08cdb79abea..2cde465440b 100644 --- a/tools/marvin/marvin/sandbox/basic/setup.properties +++ b/tools/marvin/marvin/sandbox/basic/setup.properties @@ -9,7 +9,7 @@ workers=10 use.user.concentrated.pod.allocation=false vm.allocation.algorithm=random vm.op.wait.interval=5 -guest.domain.suffix=sandbox.kvm +guest.domain.suffix=sandbox.xen instance.name=QA direct.agent.load.size=1000 default.page.size=10000 @@ -17,27 +17,25 @@ check.pod.cidrs=true secstorage.allowed.internal.sites=10.147.28.0/24 [environment] dns=10.147.28.6 -mshost=localhost -mysql.host=localhost +mshost=10.147.39.69 +mysql.host=10.147.39.69 mysql.cloud.user=cloud mysql.cloud.passwd=cloud [cloudstack] -#guest VLAN -zone.vlan=675-679 #management network -private.gateway=10.147.29.1 -private.pod.startip=10.147.29.150 -private.pod.endip=10.147.29.159 -private.netmask=255.255.255.0 +private.gateway=10.147.40.1 +private.pod.startip=10.147.41.121 +private.pod.endip=10.147.41.160 +private.netmask=255.255.254.0 #public network -public.gateway=10.147.31.1 -public.vlan.startip=10.147.31.150 -public.vlan.endip=10.147.31.159 -public.netmask=255.255.255.0 +public.gateway=10.147.40.1 +public.vlan.startip=10.147.41.162 +public.vlan.endip=10.147.41.200 +public.netmask=255.255.254.0 #hypervisor host information -hypervisor=Simulator -host=sim +hypervisor=XenServer +host=10.147.40.10 host.password=password #storage pools -primary.pool=nfs://10.147.28.6:/export/home/sandbox/kamakura -secondary.pool=nfs://10.147.28.6:/export/home/sandbox/sstor +primary.pool=nfs://10.147.28.7:/export/home/automation/sadhu/primary +secondary.pool=nfs://10.147.28.6:/export/home/automation/sadhu/secondary From 91b6e09e6d46edf9484423bb1e2b36a5ec8fa74f Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sat, 7 Jul 2012 17:59:39 +0530 Subject: [PATCH 23/66] The NoseTestLoader to pick cloudStackTestCase as tests --- tools/marvin/marvin/NoseTestExecuteEngine.py | 98 +++++++++++--------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/tools/marvin/marvin/NoseTestExecuteEngine.py b/tools/marvin/marvin/NoseTestExecuteEngine.py index ca1afb4f528..9d7944a1399 100644 --- a/tools/marvin/marvin/NoseTestExecuteEngine.py +++ b/tools/marvin/marvin/NoseTestExecuteEngine.py @@ -18,33 +18,49 @@ from functools import partial import unittest import nose -import nose.config import nose.core import os import sys import logging +import xmlrunner from cloudstackTestCase import cloudstackTestCase -from nose.suite import ContextSuite, ContextSuiteFactory - -class CloudStackTestSelector(nose.selector.Selector): - """ - custom test selector for cloudstackTestCase - """ - - def wantClass(self, cls): - if issubclass(cls, cloudstackTestCase): - return nose.selector.Selector.wantClass(self, cls) def testCaseLogger(message, logger=None): if logger is not None: logger.debug(message) + +class NoseCloudStackTestLoader(nose.loader.TestLoader): + """ + Custom test loader for the cloudstackTestCase to be loaded into nose + """ + + def loadTestsFromTestCase(self, testCaseClass): + if issubclass(testCaseClass, cloudstackTestCase): + testCaseNames = self.getTestCaseNames(testCaseClass) + tests = [] + for testCaseName in testCaseNames: + testCase = testCaseClass(testCaseName) + tests.append(testCase) + return self.suiteClass(tests) + else: + return super(NoseCloudStackTestLoader, self).loadTestsFromTestCase(testCaseClass) + + def loadTestsFromName(self, name, module=None, discovered=False): + return nose.loader.TestLoader.loadTestsFromName(self, name, module=module, discovered=discovered) + + def loadTestsFromNames(self, names, module=None): + return nose.loader.TestLoader.loadTestsFromNames(self, names, module=module) + class NoseTestExecuteEngine(object): - def __init__(self, testclient=None, workingdir=None, clientLog=None, resultLog=None, format="text"): + """ + Runs the CloudStack tests using nose as the execution engine + """ + + def __init__(self, testclient=None, workingdir=None, filename=None, clientLog=None, resultLog=None, format="text"): self.testclient = testclient self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") self.suite = [] - realPath = os.path.abspath(workingdir) if clientLog is not None: self.logfile = clientLog @@ -61,42 +77,38 @@ class NoseTestExecuteEngine(object): fp = open(resultLog, "w") self.testResultLogFile = fp else: - self.testResultLogFile = sys.stdout + self.testResultLogFile = sys.stderr - if workingdir is not None and os.path.exists(realPath + '/' + '__init__.py'): - self.loader = nose.loader.TestLoader() - [self.suite.append(test) for test in self.loader.discover(workingdir, "test*.py")] + if workingdir is not None: + self.loader = NoseCloudStackTestLoader() + self.suite = self.loader.loadTestsFromName(workingdir) for test in self.suite: - self.injectTestCase(test) - print self.suite[0].countTestCases() + self.injectClients(test) + elif filename is not None: + self.loader = NoseCloudStackTestLoader() + self.suite = self.loader.loadTestsFromFile(filename) + for test in self.suite: + self.injectClients(test) else: - raise Exception("Single module test runs unsupported using Nose") - + raise EnvironmentError("Need to give either a test directory or a test file") + if format == "text": self.runner = nose.core.TextTestRunner(stream=self.testResultLogFile, descriptions=1, verbosity=2, config=None) else: - raise Exception("XML runner not supported under nose") + self.runner = xmlrunner.XMLTestRunner(output='xml-reports', verbose=True) def runTests(self): - #testProgram = nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner = self.runner, testLoader = self.loader) - testProgram = nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner = self.runner, suite = self.suite) - testProgram.runTests() + nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner=self.runner, testLoader=self.loader) - def injectTestCase(self, testSuites): - for test in testSuites: - if isinstance(test, unittest.BaseTestSuite): - self.injectTestCase(test) - else: - #logger bears the name of the test class - testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) - fh = logging.FileHandler(self.logfile) - fh.setFormatter(self.logformat) - testcaselogger.addHandler(fh) - testcaselogger.setLevel(logging.DEBUG) - - #inject testclient and logger into each unittest - setattr(test, "testClient", self.testclient) - setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) - setattr(test.__class__, "clstestclient", self.testclient) - if hasattr(test, "UserName"): - self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) + def injectClients(self, test): + testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) + fh = logging.FileHandler(self.logfile) + fh.setFormatter(self.logformat) + testcaselogger.addHandler(fh) + testcaselogger.setLevel(logging.DEBUG) + + setattr(test, "testClient", self.testclient) + setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) + setattr(test.__class__, "clstestclient", self.testclient) + if hasattr(test, "UserName"): + self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) From db5687d69182574ae439e4caa4e4181eb38c03a4 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 9 Jul 2012 12:39:14 +0530 Subject: [PATCH 24/66] enhancement related to -x to take directory name/path to store xml reports Conflicts: tools/marvin/marvin/TestCaseExecuteEngine.py --- tools/marvin/marvin/TestCaseExecuteEngine.py | 8 ++++++-- tools/marvin/marvin/deployAndRun.py | 10 ++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py index 07df5633c99..52a6dacc726 100644 --- a/tools/marvin/marvin/TestCaseExecuteEngine.py +++ b/tools/marvin/marvin/TestCaseExecuteEngine.py @@ -27,7 +27,7 @@ def testCaseLogger(message, logger=None): logger.debug(message) class TestCaseExecuteEngine(object): - def __init__(self, testclient, testcaseLogFile=None, testResultLogFile=None, format="text"): + def __init__(self, testclient, testcaseLogFile=None, testResultLogFile=None, format="text", xmlDir="xml-reports"): """ Initialize the testcase execution engine, just the basics here @var testcaseLogFile: client log file @@ -55,6 +55,10 @@ class TestCaseExecuteEngine(object): self.testResultLogFile = fp else: self.testResultLogFile = sys.stdout + if self.format == "xml" and (xmlDir is not None): + self.xmlDir = xmlDir + + def loadTestsFromDir(self, testDirectory): """ Load the test suites from a package with multiple test files """ @@ -91,4 +95,4 @@ class TestCaseExecuteEngine(object): if self.format == "text": unittest.TextTestRunner(stream=self.testResultLogFile, verbosity=2).run(self.suite) elif self.format == "xml": - xmlrunner.XMLTestRunner(output='xml-reports', verbose=True).run(self.suite) + xmlrunner.XMLTestRunner(output=self.xmlDir, verbose=True).run(self.suite) diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py index 80d74e4b63e..5b9e4dc59f1 100644 --- a/tools/marvin/marvin/deployAndRun.py +++ b/tools/marvin/marvin/deployAndRun.py @@ -31,7 +31,7 @@ if __name__ == "__main__": parser.add_option("-l", "--load", dest="load", action="store_true", help="only load config, do not deploy, it will only run testcase") parser.add_option("-f", "--file", dest="module", help="run tests in the given file") parser.add_option("-n", "--nose", dest="nose", action="store_true", help="run tests using nose") - parser.add_option("-x", "--xml", dest="xmlrunner", action="store_true", help="use the xml runner to generate xml reports") + parser.add_option("-x", "--xml", dest="xmlrunner", action="store", default="./xml-reports", help="use the xml runner to generate xml reports and path to store xml files") (options, args) = parser.parse_args() testResultLogFile = None @@ -48,7 +48,9 @@ if __name__ == "__main__": deploy.deploy() format = "text" - if options.xmlrunner: + xmlDir = "xml-reports" + if options.xmlrunner is not None: + xmlDir = options.xmlrunner format = "xml" if options.testCaseFolder is None: @@ -60,7 +62,7 @@ if __name__ == "__main__": engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format) engine.runTestsFromFile(options.module) else: - engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format) + engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) engine.loadTestsFromFile(options.module) engine.run() else: @@ -68,6 +70,6 @@ if __name__ == "__main__": engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, clientLog=testCaseLogFile, resultLog=testResultLogFile, workingdir=options.testCaseFolder, format=format) engine.runTests() else: - engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format) + engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) engine.loadTestsFromDir(options.testCaseFolder) engine.run() From 84b69e6e0a8fc99ac57d3024acadc3cd35ec3f79 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sat, 7 Jul 2012 21:51:08 +0530 Subject: [PATCH 25/66] injecting the testclient during Test Loader process Without this the tests do not have access to the client APIs --- tools/marvin/marvin/NoseTestExecuteEngine.py | 48 ++++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/tools/marvin/marvin/NoseTestExecuteEngine.py b/tools/marvin/marvin/NoseTestExecuteEngine.py index 9d7944a1399..9499c9032a4 100644 --- a/tools/marvin/marvin/NoseTestExecuteEngine.py +++ b/tools/marvin/marvin/NoseTestExecuteEngine.py @@ -40,6 +40,7 @@ class NoseCloudStackTestLoader(nose.loader.TestLoader): tests = [] for testCaseName in testCaseNames: testCase = testCaseClass(testCaseName) + self._injectClients(testCase) tests.append(testCase) return self.suiteClass(tests) else: @@ -50,7 +51,25 @@ class NoseCloudStackTestLoader(nose.loader.TestLoader): def loadTestsFromNames(self, names, module=None): return nose.loader.TestLoader.loadTestsFromNames(self, names, module=module) - + + def setClient(self, client): + self.testclient = client + + def setClientLog(self, clientlog): + self.log = clientlog + + def _injectClients(self, test): + testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) + fh = logging.FileHandler(self.log) + fh.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")) + testcaselogger.addHandler(fh) + testcaselogger.setLevel(logging.DEBUG) + + setattr(test, "testClient", self.testclient) + setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) + setattr(test.__class__, "clstestclient", self.testclient) + if hasattr(test, "UserName"): + self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) class NoseTestExecuteEngine(object): """ @@ -81,14 +100,14 @@ class NoseTestExecuteEngine(object): if workingdir is not None: self.loader = NoseCloudStackTestLoader() - self.suite = self.loader.loadTestsFromName(workingdir) - for test in self.suite: - self.injectClients(test) + self.loader.setClient(self.testclient) + self.loader.setClientLog(self.logfile) + self.suite = self.loader.loadTestsFromDir(workingdir) elif filename is not None: self.loader = NoseCloudStackTestLoader() + self.loader.setClient(self.testclient) + self.loader.setClientLog(self.logfile) self.suite = self.loader.loadTestsFromFile(filename) - for test in self.suite: - self.injectClients(test) else: raise EnvironmentError("Need to give either a test directory or a test file") @@ -98,17 +117,6 @@ class NoseTestExecuteEngine(object): self.runner = xmlrunner.XMLTestRunner(output='xml-reports', verbose=True) def runTests(self): - nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner=self.runner, testLoader=self.loader) - - def injectClients(self, test): - testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) - fh = logging.FileHandler(self.logfile) - fh.setFormatter(self.logformat) - testcaselogger.addHandler(fh) - testcaselogger.setLevel(logging.DEBUG) - - setattr(test, "testClient", self.testclient) - setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) - setattr(test.__class__, "clstestclient", self.testclient) - if hasattr(test, "UserName"): - self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) + #nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner=self.runner, testLoader=self.loader) + nose.core.TestProgram(argv=["--process-timeout=3600"], \ + testRunner=self.runner, suite=self.suite) From 0ab7a9289f52acc3f25f92984c9508684c1321fd Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 20 Jul 2012 17:26:42 +0530 Subject: [PATCH 26/66] Support added for attrib, multiprocess and Xunit coverage plugins Conflicts: tools/marvin/marvin/NoseTestExecuteEngine.py --- tools/marvin/marvin/NoseTestExecuteEngine.py | 75 +++++++------------- tools/marvin/marvin/cloudstackTestCase.py | 2 +- 2 files changed, 27 insertions(+), 50 deletions(-) diff --git a/tools/marvin/marvin/NoseTestExecuteEngine.py b/tools/marvin/marvin/NoseTestExecuteEngine.py index 9499c9032a4..25d5c9343e9 100644 --- a/tools/marvin/marvin/NoseTestExecuteEngine.py +++ b/tools/marvin/marvin/NoseTestExecuteEngine.py @@ -24,52 +24,10 @@ import sys import logging import xmlrunner from cloudstackTestCase import cloudstackTestCase - -def testCaseLogger(message, logger=None): - if logger is not None: - logger.debug(message) - -class NoseCloudStackTestLoader(nose.loader.TestLoader): - """ - Custom test loader for the cloudstackTestCase to be loaded into nose - """ - - def loadTestsFromTestCase(self, testCaseClass): - if issubclass(testCaseClass, cloudstackTestCase): - testCaseNames = self.getTestCaseNames(testCaseClass) - tests = [] - for testCaseName in testCaseNames: - testCase = testCaseClass(testCaseName) - self._injectClients(testCase) - tests.append(testCase) - return self.suiteClass(tests) - else: - return super(NoseCloudStackTestLoader, self).loadTestsFromTestCase(testCaseClass) - - def loadTestsFromName(self, name, module=None, discovered=False): - return nose.loader.TestLoader.loadTestsFromName(self, name, module=module, discovered=discovered) - - def loadTestsFromNames(self, names, module=None): - return nose.loader.TestLoader.loadTestsFromNames(self, names, module=module) - - def setClient(self, client): - self.testclient = client - - def setClientLog(self, clientlog): - self.log = clientlog - - def _injectClients(self, test): - testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) - fh = logging.FileHandler(self.log) - fh.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")) - testcaselogger.addHandler(fh) - testcaselogger.setLevel(logging.DEBUG) - - setattr(test, "testClient", self.testclient) - setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) - setattr(test.__class__, "clstestclient", self.testclient) - if hasattr(test, "UserName"): - self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) +from marvinPlugin import MarvinPlugin +from nose.plugins.xunit import Xunit +from nose.plugins.attrib import AttributeSelector +from nose.plugins.multiprocess import MultiProcessTestRunner class NoseTestExecuteEngine(object): """ @@ -111,12 +69,31 @@ class NoseTestExecuteEngine(object): else: raise EnvironmentError("Need to give either a test directory or a test file") + plug_mgr = nose.plugins.manager.PluginManager() + plug_mgr.addPlugin(self.test_picker) + plug_mgr.addPlugin(Xunit()) + plug_mgr.addPlugin(AttributeSelector()) + plug_mgr.addPlugin(MultiProcessTestRunner()) + self.cfg = nose.config.Config() + self.cfg.plugins = plug_mgr + if format == "text": self.runner = nose.core.TextTestRunner(stream=self.testResultLogFile, descriptions=1, verbosity=2, config=None) else: self.runner = xmlrunner.XMLTestRunner(output='xml-reports', verbose=True) def runTests(self): - #nose.core.TestProgram(argv=["--process-timeout=3600"], testRunner=self.runner, testLoader=self.loader) - nose.core.TestProgram(argv=["--process-timeout=3600"], \ - testRunner=self.runner, suite=self.suite) + options = ["--process-timeout=3600", "--with-xunit", "-a tags=advanced", "--processes=5"] #TODO: Add support for giving nose args + #DEBUG +# options = ["--process-timeout=3600", "--with-xunit", "--collect-only"] + #DEBUG +# options = ["--process-timeout=3600"] + options.append("-w%s" %self.workingdir) + + if self.workingdir is not None: + nose.core.TestProgram(argv=options, testRunner=self.runner, + config=self.cfg) + elif self.filename is not None: + tests = self.loader.loadTestsFromFile(self.filename) + nose.core.TestProgram(argv=options, testRunner=self.runner, + config=self.cfg) diff --git a/tools/marvin/marvin/cloudstackTestCase.py b/tools/marvin/marvin/cloudstackTestCase.py index a85eef7e1dd..4ec764c58bf 100644 --- a/tools/marvin/marvin/cloudstackTestCase.py +++ b/tools/marvin/marvin/cloudstackTestCase.py @@ -48,7 +48,7 @@ class cloudstackTestCase(unittest.case.TestCase): def __init__(self, args): unittest.case.TestCase.__init__(self, args) - self.testClient = cloudstackTestClient.cloudstackTestClient() +# self.testClient = cloudstackTestClient.cloudstackTestClient() @classmethod def getClsTestClient(cls): From 9af88ad44d4465e3704fdb8917542a70f003b318 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 19 Jul 2012 23:27:18 +0530 Subject: [PATCH 27/66] Plugin support to pick test cases using marvin. Using this plugin Nose will drive tests and this also allows using other nose plugins. Cmd Line plugin support to be added Conflicts: tools/marvin/marvin/NoseTestExecuteEngine.py --- tools/marvin/marvin/NoseTestExecuteEngine.py | 25 +++++---- tools/marvin/marvin/TestCaseExecuteEngine.py | 2 - tools/marvin/marvin/deployAndRun.py | 13 ++--- tools/marvin/marvin/marvinPlugin.py | 54 ++++++++++++++++++++ 4 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 tools/marvin/marvin/marvinPlugin.py diff --git a/tools/marvin/marvin/NoseTestExecuteEngine.py b/tools/marvin/marvin/NoseTestExecuteEngine.py index 25d5c9343e9..5304afeeb91 100644 --- a/tools/marvin/marvin/NoseTestExecuteEngine.py +++ b/tools/marvin/marvin/NoseTestExecuteEngine.py @@ -29,12 +29,13 @@ from nose.plugins.xunit import Xunit from nose.plugins.attrib import AttributeSelector from nose.plugins.multiprocess import MultiProcessTestRunner + class NoseTestExecuteEngine(object): """ Runs the CloudStack tests using nose as the execution engine """ - def __init__(self, testclient=None, workingdir=None, filename=None, clientLog=None, resultLog=None, format="text"): + def __init__(self, testclient=None, workingdir=None, filename=None, clientLog=None, resultLog=None, format="text", xmlDir='xml-reports'): self.testclient = testclient self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") self.suite = [] @@ -57,15 +58,15 @@ class NoseTestExecuteEngine(object): self.testResultLogFile = sys.stderr if workingdir is not None: - self.loader = NoseCloudStackTestLoader() - self.loader.setClient(self.testclient) - self.loader.setClientLog(self.logfile) - self.suite = self.loader.loadTestsFromDir(workingdir) + self.workingdir = workingdir + self.test_picker = MarvinPlugin() + self.test_picker.setClient(self.testclient) + self.test_picker.setClientLog(self.logfile) elif filename is not None: - self.loader = NoseCloudStackTestLoader() - self.loader.setClient(self.testclient) - self.loader.setClientLog(self.logfile) - self.suite = self.loader.loadTestsFromFile(filename) + self.test_picker = MarvinPlugin() + self.test_picker.setClient(self.testclient) + self.test_picker.setClientLog(self.logfile) + self.filename = filename else: raise EnvironmentError("Need to give either a test directory or a test file") @@ -78,9 +79,11 @@ class NoseTestExecuteEngine(object): self.cfg.plugins = plug_mgr if format == "text": - self.runner = nose.core.TextTestRunner(stream=self.testResultLogFile, descriptions=1, verbosity=2, config=None) + self.runner = \ + nose.core.TextTestRunner(stream=self.testResultLogFile, + descriptions=1, verbosity=2, config=self.cfg) else: - self.runner = xmlrunner.XMLTestRunner(output='xml-reports', verbose=True) + self.runner = xmlrunner.XMLTestRunner(output=xmlDir, verbose=True) def runTests(self): options = ["--process-timeout=3600", "--with-xunit", "-a tags=advanced", "--processes=5"] #TODO: Add support for giving nose args diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py index 52a6dacc726..44a44aa141c 100644 --- a/tools/marvin/marvin/TestCaseExecuteEngine.py +++ b/tools/marvin/marvin/TestCaseExecuteEngine.py @@ -58,8 +58,6 @@ class TestCaseExecuteEngine(object): if self.format == "xml" and (xmlDir is not None): self.xmlDir = xmlDir - - def loadTestsFromDir(self, testDirectory): """ Load the test suites from a package with multiple test files """ self.suite = self.loader.discover(testDirectory) diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py index 5b9e4dc59f1..31faa09c389 100644 --- a/tools/marvin/marvin/deployAndRun.py +++ b/tools/marvin/marvin/deployAndRun.py @@ -22,7 +22,8 @@ from optparse import OptionParser import os if __name__ == "__main__": - parser = OptionParser() + + parser = OptionParser() #TODO: deprecate and use the argparse module parser.add_option("-c", "--config", action="store", default="./datacenterCfg", dest="config", help="the path where the json config file generated, by default is ./datacenterCfg") parser.add_option("-d", "--directory", dest="testCaseFolder", help="the test case directory") @@ -31,7 +32,7 @@ if __name__ == "__main__": parser.add_option("-l", "--load", dest="load", action="store_true", help="only load config, do not deploy, it will only run testcase") parser.add_option("-f", "--file", dest="module", help="run tests in the given file") parser.add_option("-n", "--nose", dest="nose", action="store_true", help="run tests using nose") - parser.add_option("-x", "--xml", dest="xmlrunner", action="store", default="./xml-reports", help="use the xml runner to generate xml reports and path to store xml files") + parser.add_option("-x", "--xml", dest="xmlrunner", help="use the xml runner to generate xml reports and path to store xml files") (options, args) = parser.parse_args() testResultLogFile = None @@ -47,8 +48,8 @@ if __name__ == "__main__": else: deploy.deploy() - format = "text" - xmlDir = "xml-reports" + format = "text" + xmlDir = None if options.xmlrunner is not None: xmlDir = options.xmlrunner format = "xml" @@ -59,7 +60,7 @@ if __name__ == "__main__": exit(1) else: if options.nose: - engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format) + engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) engine.runTestsFromFile(options.module) else: engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) @@ -67,7 +68,7 @@ if __name__ == "__main__": engine.run() else: if options.nose: - engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, clientLog=testCaseLogFile, resultLog=testResultLogFile, workingdir=options.testCaseFolder, format=format) + engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, clientLog=testCaseLogFile, resultLog=testResultLogFile, workingdir=options.testCaseFolder, format=format, xmlDir=xmlDir) engine.runTests() else: engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py new file mode 100644 index 00000000000..9d523621564 --- /dev/null +++ b/tools/marvin/marvin/marvinPlugin.py @@ -0,0 +1,54 @@ +from cloudstackTestCase import cloudstackTestCase +from nose.plugins.base import Plugin +from functools import partial +import logging + +def testCaseLogger(message, logger=None): + if logger is not None: + logger.debug(message) + +class MarvinPlugin(Plugin): + """ + Custom test loader for the cloudstackTestCase to be loaded into nose + """ + + name = "marvin" + def configure(self, options, conf): + self.enabled = 1 + self.enableOpt = "--with-marvin" + return Plugin.configure(self, options, conf) + + def options(self, parser, env): + Plugin.options(self, parser, env) + + def __init__(self): + Plugin.__init__(self) + + def wantClass(self, cls): + if issubclass(cls, cloudstackTestCase): + return True + return None + + def loadTestsFromTestCase(self, cls): + self._injectClients(cls) + + def setClient(self, client): + if client: + self.testclient = client + + def setClientLog(self, clientlog): + if clientlog: + self.log = clientlog + + def _injectClients(self, test): + testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__class__.__name__) + fh = logging.FileHandler(self.log) + fh.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")) + testcaselogger.addHandler(fh) + testcaselogger.setLevel(logging.DEBUG) + + setattr(test, "testClient", self.testclient) + setattr(test, "debug", partial(testCaseLogger, logger=testcaselogger)) + setattr(test, "clstestclient", self.testclient) + if hasattr(test, "UserName"): + self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) From ed113ca8445199a6adc246d3cbd5a249bb4b190e Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 23 Jul 2012 10:47:48 +0530 Subject: [PATCH 28/66] Correcting the imports for HTTPException --- tools/marvin/marvin/cloudstackConnection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index 37919c082fe..d70c192406e 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -17,6 +17,7 @@ import urllib2 import urllib +import httplib import base64 import hmac import hashlib @@ -76,7 +77,7 @@ class cloudConnection(object): self.logging.critical("failed to reach %s because of %s"%(self.mgtSvr, e.reason)) elif hasattr(e, 'code'): self.logging.critical("server returned %d error code"%e.code) - except HTTPException, h: + except httplib.HTTPException, h: self.logging.debug("encountered http Exception %s"%h.args) if self.retries > 0: self.retries = self.retries - 1 From 13857700d38ed8a221f2353e927c8cd2d2df56c9 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 23 Jul 2012 19:23:04 +0530 Subject: [PATCH 29/66] Plugin-izing the testcase runner * setup.py is the installer for marvin-nose plugin * marvin-nose drive all tests using nose with other plugins like xunit, coverage, multiprocess execution etc * -n option deprecated. All tests driven by nosetests --with-marvin --- tools/marvin/marvin/deployAndRun.py | 22 +++------ tools/marvin/marvin/marvinPlugin.py | 73 ++++++++++++++++++++++++----- tools/marvin/marvin/setup.py | 29 ++++++++++++ 3 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 tools/marvin/marvin/setup.py diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py index 31faa09c389..1c82d9fcc2e 100644 --- a/tools/marvin/marvin/deployAndRun.py +++ b/tools/marvin/marvin/deployAndRun.py @@ -17,7 +17,6 @@ import deployDataCenter import TestCaseExecuteEngine -import NoseTestExecuteEngine from optparse import OptionParser import os @@ -31,7 +30,6 @@ if __name__ == "__main__": parser.add_option("-t", "--client", dest="testcaselog", help="test case log file") parser.add_option("-l", "--load", dest="load", action="store_true", help="only load config, do not deploy, it will only run testcase") parser.add_option("-f", "--file", dest="module", help="run tests in the given file") - parser.add_option("-n", "--nose", dest="nose", action="store_true", help="run tests using nose") parser.add_option("-x", "--xml", dest="xmlrunner", help="use the xml runner to generate xml reports and path to store xml files") (options, args) = parser.parse_args() @@ -59,18 +57,10 @@ if __name__ == "__main__": parser.print_usage() exit(1) else: - if options.nose: - engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) - engine.runTestsFromFile(options.module) - else: - engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) - engine.loadTestsFromFile(options.module) - engine.run() + engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) + engine.loadTestsFromFile(options.module) + engine.run() else: - if options.nose: - engine = NoseTestExecuteEngine.NoseTestExecuteEngine(deploy.testClient, clientLog=testCaseLogFile, resultLog=testResultLogFile, workingdir=options.testCaseFolder, format=format, xmlDir=xmlDir) - engine.runTests() - else: - engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) - engine.loadTestsFromDir(options.testCaseFolder) - engine.run() + engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient, testCaseLogFile, testResultLogFile, format, xmlDir) + engine.loadTestsFromDir(options.testCaseFolder) + engine.run() diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index 9d523621564..b99c14fa041 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -1,7 +1,10 @@ -from cloudstackTestCase import cloudstackTestCase +import marvin +import logging +import nose.core +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin import deployDataCenter from nose.plugins.base import Plugin from functools import partial -import logging def testCaseLogger(message, logger=None): if logger is not None: @@ -9,21 +12,69 @@ def testCaseLogger(message, logger=None): class MarvinPlugin(Plugin): """ - Custom test loader for the cloudstackTestCase to be loaded into nose + Custom plugin for the cloudstackTestCases to be run using nose """ name = "marvin" - def configure(self, options, conf): + def configure(self, options, config): self.enabled = 1 self.enableOpt = "--with-marvin" - return Plugin.configure(self, options, conf) + self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") + + if options.debug_log: + self.logger = logging.getLogger("NoseTestExecuteEngine") + self.debug_stream = logging.FileHandler(options.debug_log) + self.debug_stream.setFormatter(self.logformat) + self.logger.addHandler(self.debug_stream) + self.logger.setLevel(logging.DEBUG) + + if options.result_log: + ch = logging.StreamHandler() + ch.setLevel(logging.ERROR) + ch.setFormatter(self.logformat) + self.logger.addHandler(ch) + self.result_stream = open(options.result_log, "w") + else: + self.result_stream = sys.stderr + + deploy = deployDataCenter.deployDataCenters(options.config) + deploy.loadCfg() if options.load else deploy.deploy() + self.setClient(deploy.testClient) + + cfg = nose.config.Config() + cfg.logStream = self.result_stream + cfg.debugLog = self.debug_stream + cfg.workingDir = options.test_dir + + self.testrunner = nose.core.TextTestRunner(stream=self.result_stream, descriptions=True, verbosity=2, config=config) def options(self, parser, env): + """ + Register command line options + """ + parser.add_option("--marvin-config", action="store", + default=env.get('MARVIN_CONFIG', './datacenter.cfg'), + dest="config", + help="Marvin's configuration file where the datacenter information is specified [MARVIN_CONFIG]") + parser.add_option("--result-log", action="store", + default=env.get('RESULT_LOG', 'result.log'), + dest="result_log", + help="The path to the results file where test summary will be written to [RESULT_LOG]") + parser.add_option("--client-log", action="store", + default=env.get('DEBUG_LOG', 'debug.log'), + dest="debug_log", + help="The path to the testcase debug logs [DEBUG_LOG]") + parser.add_option("--load", action="store_true", default=False, dest="load", + help="Only load the deployment configuration given") + Plugin.options(self, parser, env) def __init__(self): Plugin.__init__(self) + def prepareTestRunner(self, runner): + return self.testrunner + def wantClass(self, cls): if issubclass(cls, cloudstackTestCase): return True @@ -36,15 +87,10 @@ class MarvinPlugin(Plugin): if client: self.testclient = client - def setClientLog(self, clientlog): - if clientlog: - self.log = clientlog - def _injectClients(self, test): - testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__class__.__name__) - fh = logging.FileHandler(self.log) - fh.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")) - testcaselogger.addHandler(fh) + testcaselogger = logging.getLogger("testclient.testcase.%s" % test.__name__) + self.debug_stream.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")) + testcaselogger.addHandler(self.debug_stream) testcaselogger.setLevel(logging.DEBUG) setattr(test, "testClient", self.testclient) @@ -52,3 +98,4 @@ class MarvinPlugin(Plugin): setattr(test, "clstestclient", self.testclient) if hasattr(test, "UserName"): self.testclient.createNewApiClient(test.UserName, test.DomainName, test.AcctType) + diff --git a/tools/marvin/marvin/setup.py b/tools/marvin/marvin/setup.py new file mode 100644 index 00000000000..83977f4b78f --- /dev/null +++ b/tools/marvin/marvin/setup.py @@ -0,0 +1,29 @@ +import os +from setuptools import setup + +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read().strip() + +VERSION = '0.1.0' + +setup( + name = "marvin-nose", + version = VERSION, + author = "Prasanna Santhanam", + author_email = "Prasanna.Santhanam@citrix.com", + description = "Run tests written using CloudStack's Marvin testclient", + license = 'ASL 2.0', + classifiers = [ + "Intended Audience :: Developers", + "Topic :: Software Development :: Testing", + "Programming Language :: Python", + ], + + py_modules = ['marvinPlugin'], + zip_safe = False, + + entry_points = { + 'nose.plugins': ['marvinPlugin = marvinPlugin:MarvinPlugin'] + }, + install_requires = ['nose', 'marvin'], +) From 766242676947a0ec308ae4192f8d81763a361251 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 23 Jul 2012 19:25:07 +0530 Subject: [PATCH 30/66] All responsibilty for running through nose belongs to the marvin-nose plugin Conflicts: tools/marvin/marvin/NoseTestExecuteEngine.py --- tools/marvin/marvin/NoseTestExecuteEngine.py | 102 ------------------- 1 file changed, 102 deletions(-) delete mode 100644 tools/marvin/marvin/NoseTestExecuteEngine.py diff --git a/tools/marvin/marvin/NoseTestExecuteEngine.py b/tools/marvin/marvin/NoseTestExecuteEngine.py deleted file mode 100644 index 5304afeeb91..00000000000 --- a/tools/marvin/marvin/NoseTestExecuteEngine.py +++ /dev/null @@ -1,102 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -from functools import partial -import unittest -import nose -import nose.core -import os -import sys -import logging -import xmlrunner -from cloudstackTestCase import cloudstackTestCase -from marvinPlugin import MarvinPlugin -from nose.plugins.xunit import Xunit -from nose.plugins.attrib import AttributeSelector -from nose.plugins.multiprocess import MultiProcessTestRunner - - -class NoseTestExecuteEngine(object): - """ - Runs the CloudStack tests using nose as the execution engine - """ - - def __init__(self, testclient=None, workingdir=None, filename=None, clientLog=None, resultLog=None, format="text", xmlDir='xml-reports'): - self.testclient = testclient - self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") - self.suite = [] - - if clientLog is not None: - self.logfile = clientLog - self.logger = logging.getLogger("NoseTestExecuteEngine") - fh = logging.FileHandler(self.logfile) - fh.setFormatter(self.logformat) - self.logger.addHandler(fh) - self.logger.setLevel(logging.DEBUG) - if resultLog is not None: - ch = logging.StreamHandler() - ch.setLevel(logging.ERROR) - ch.setFormatter(self.logformat) - self.logger.addHandler(ch) - fp = open(resultLog, "w") - self.testResultLogFile = fp - else: - self.testResultLogFile = sys.stderr - - if workingdir is not None: - self.workingdir = workingdir - self.test_picker = MarvinPlugin() - self.test_picker.setClient(self.testclient) - self.test_picker.setClientLog(self.logfile) - elif filename is not None: - self.test_picker = MarvinPlugin() - self.test_picker.setClient(self.testclient) - self.test_picker.setClientLog(self.logfile) - self.filename = filename - else: - raise EnvironmentError("Need to give either a test directory or a test file") - - plug_mgr = nose.plugins.manager.PluginManager() - plug_mgr.addPlugin(self.test_picker) - plug_mgr.addPlugin(Xunit()) - plug_mgr.addPlugin(AttributeSelector()) - plug_mgr.addPlugin(MultiProcessTestRunner()) - self.cfg = nose.config.Config() - self.cfg.plugins = plug_mgr - - if format == "text": - self.runner = \ - nose.core.TextTestRunner(stream=self.testResultLogFile, - descriptions=1, verbosity=2, config=self.cfg) - else: - self.runner = xmlrunner.XMLTestRunner(output=xmlDir, verbose=True) - - def runTests(self): - options = ["--process-timeout=3600", "--with-xunit", "-a tags=advanced", "--processes=5"] #TODO: Add support for giving nose args - #DEBUG -# options = ["--process-timeout=3600", "--with-xunit", "--collect-only"] - #DEBUG -# options = ["--process-timeout=3600"] - options.append("-w%s" %self.workingdir) - - if self.workingdir is not None: - nose.core.TestProgram(argv=options, testRunner=self.runner, - config=self.cfg) - elif self.filename is not None: - tests = self.loader.loadTestsFromFile(self.filename) - nose.core.TestProgram(argv=options, testRunner=self.runner, - config=self.cfg) From ed7f72b629e4e95db0871ab0c571d0caa48ed34e Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Wed, 25 Jul 2012 18:51:04 +0530 Subject: [PATCH 31/66] Enable VpcVirtualRouter when deploying advanced zone --- tools/marvin/marvin/deployDataCenter.py | 45 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 91045cd741f..bd0217f8cab 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -196,26 +196,45 @@ class deployDataCenters(): vrconfig.id = vrprovid vrconfigresponse = \ self.apiClient.configureVirtualRouterElement(vrconfig) + + upnetprov = \ + updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + upnetprov.id = vrprov.nspid + upnetprov.state = "Enabled" + upnetprovresponse = \ + self.apiClient.updateNetworkServiceProvider(upnetprov) if zone.networktype == "Basic" and zone.securitygroupenabled: sgprovider = configGenerator.provider() sgprovider.name = "SecurityGroupProvider" zone.providers.append(sgprovider) - - for prov in zone.providers: - pnetprov = \ - listNetworkServiceProviders.listNetworkServiceProvidersCmd() + + if zone.networktype == "Advanced": + pnetprov = listNetworkServiceProviders.listNetworkServiceProvidersCmd() pnetprov.physicalnetworkid = phynetwrk.id - pnetprov.name = prov.name pnetprov.state = "Disabled" - pnetprovs = self.apiClient.listNetworkServiceProviders(pnetprov) - - upnetprov = \ - updateNetworkServiceProvider.updateNetworkServiceProviderCmd() - upnetprov.id = pnetprovs[0].id - upnetprov.state = "Enabled" - upnetprovresponse = \ - self.apiClient.updateNetworkServiceProvider(upnetprov) + pnetprov.name = "VpcVirtualRouter" + pnetprovres = self.apiClient.listNetworkServiceProviders(pnetprov) + + if len(pnetprovres) > 0: + vpcvrprov = listVirtualRouterElements.listVirtualRouterElementsCmd() + vpcvrprov.nspid = pnetprovres[0].id + vpcvrprovresponse = self.apiClient.listVirtualRouterElements(vpcvrprov) + vpcvrprovid = vpcvrprovresponse[0].id + + vpcvrconfig = \ + configureVirtualRouterElement.configureVirtualRouterElementCmd() + vpcvrconfig.enabled = "true" + vpcvrconfig.id = vpcvrprovid + vpcvrconfigresponse = \ + self.apiClient.configureVirtualRouterElement(vpcvrconfig) + + upnetprov = \ + updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + upnetprov.id = vpcvrprov.nspid + upnetprov.state = "Enabled" + upnetprovresponse = \ + self.apiClient.updateNetworkServiceProvider(upnetprov) def addTrafficTypes(self, physical_network_id, traffictypes=None, \ network_labels=None): From 046f2d786f864cc0a5d28451117c7ea462679eee Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 26 Jul 2012 16:33:44 +0530 Subject: [PATCH 32/66] License headers for the marvin plugin and the setup checker --- tools/marvin/marvin/marvinPlugin.py | 17 +++++++++++++++++ tools/marvin/marvin/setup.py | 17 +++++++++++++++++ tools/marvin/marvin/testSetupSuccess.py | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index b99c14fa041..ace6f6cb181 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -1,3 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + import marvin import logging import nose.core diff --git a/tools/marvin/marvin/setup.py b/tools/marvin/marvin/setup.py index 83977f4b78f..dea67df8f89 100644 --- a/tools/marvin/marvin/setup.py +++ b/tools/marvin/marvin/setup.py @@ -1,3 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + import os from setuptools import setup diff --git a/tools/marvin/marvin/testSetupSuccess.py b/tools/marvin/marvin/testSetupSuccess.py index ed167a17f20..8a0034cfa9b 100644 --- a/tools/marvin/marvin/testSetupSuccess.py +++ b/tools/marvin/marvin/testSetupSuccess.py @@ -1,3 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + import marvin import unittest from marvin.cloudstackTestCase import * From 8a2135e3faede9739eac3c728c90e7fc6578db38 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 26 Jul 2012 19:57:53 +0530 Subject: [PATCH 33/66] VpcVirtualRouter is not enabled always. --- tools/marvin/marvin/deployDataCenter.py | 2 +- tools/marvin/marvin/marvinPlugin.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index bd0217f8cab..4284d12a542 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -216,7 +216,7 @@ class deployDataCenters(): pnetprov.name = "VpcVirtualRouter" pnetprovres = self.apiClient.listNetworkServiceProviders(pnetprov) - if len(pnetprovres) > 0: + if pnetprovres and len(pnetprovres) > 0: vpcvrprov = listVirtualRouterElements.listVirtualRouterElementsCmd() vpcvrprov.nspid = pnetprovres[0].id vpcvrprovresponse = self.apiClient.listVirtualRouterElements(vpcvrprov) diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index ace6f6cb181..5e0c6dadb32 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -61,7 +61,6 @@ class MarvinPlugin(Plugin): cfg = nose.config.Config() cfg.logStream = self.result_stream cfg.debugLog = self.debug_stream - cfg.workingDir = options.test_dir self.testrunner = nose.core.TextTestRunner(stream=self.result_stream, descriptions=True, verbosity=2, config=config) From 60713b7a419a5f79a62a9315957b49ccfb2adbe6 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 30 Jul 2012 16:31:53 +0530 Subject: [PATCH 34/66] Delete old cloud-usage script file --- usage/scripts/usageserver.sh | 45 ------------------------------------ 1 file changed, 45 deletions(-) delete mode 100755 usage/scripts/usageserver.sh diff --git a/usage/scripts/usageserver.sh b/usage/scripts/usageserver.sh deleted file mode 100755 index fe467a66a9c..00000000000 --- a/usage/scripts/usageserver.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# 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. - - - - -# run the usage server - -PATHSEP=':' -if [[ $OSTYPE == "cygwin" ]]; then - PATHSEP=';' - export CATALINA_HOME=`cygpath -m $CATALINA_HOME` -fi - -CP=./$PATHSEP$CATALINA_HOME/webapps/client/WEB-INF/lib/vmops-server.jar -CP=${CP}$PATHSEP$CATALINA_HOME/webapps/client/WEB-INF/lib/vmops-server-extras.jar -CP=${CP}$PATHSEP$CATALINA_HOME/webapps/client/WEB-INF/lib/vmops-utils.jar -CP=${CP}$PATHSEP$CATALINA_HOME/webapps/client/WEB-INF/lib/vmops-core.jar -CP=${CP}$PATHSEP$CATALINA_HOME/webapps/client/WEB-INF/lib/vmops-usage.jar -CP=${CP}$PATHSEP$CATALINA_HOME/conf - -for file in $CATALINA_HOME/lib/*.jar; do - CP=${CP}$PATHSEP$file -done - -#echo CP is $CP -DEBUG_OPTS= -#DEBUG_OPTS=-Xrunjdwp:transport=dt_socket,address=$1,server=y,suspend=n - -java -cp $CP $DEBUG_OPTS -Dcatalina.home=${CATALINA_HOME} -Dpid=$$ com.vmops.usage.UsageServer $* From 11c839ab1d5c7a4e3e8731612117a237d2b5640e Mon Sep 17 00:00:00 2001 From: David Nalley Date: Mon, 30 Jul 2012 09:02:38 -0400 Subject: [PATCH 35/66] adding config file for docs --- .gitignore | 1 - docs/publican.cfg | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 docs/publican.cfg diff --git a/.gitignore b/.gitignore index 7d89223ac65..b067d85024e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ dist/ cloud-*.tar.bz2 *.log *.pyc -*.cfg build.number api.log.*.gz cloud.log.*.* diff --git a/docs/publican.cfg b/docs/publican.cfg new file mode 100644 index 00000000000..fb5a16f6dc5 --- /dev/null +++ b/docs/publican.cfg @@ -0,0 +1,10 @@ +# Config::Simple 4.58 +# Tue May 29 00:57:27 2012 + +xml_lang: en-US +type: Book +docname: release-notes-3.0.4 +brand: cloudstack +chunk_first: 0 +chunk_section_depth: 0 +toc_section_depth: 1 From 90de18138df2a677df4f7f1d1e2158e1d35309f0 Mon Sep 17 00:00:00 2001 From: "chip.childers@gmail.com" Date: Mon, 30 Jul 2012 09:00:55 -0400 Subject: [PATCH 36/66] Added storage configuration to the devcloud puppet module. --- .../devcloudbox/puppet-devcloud/files/exports | 1 + .../puppet-devcloud/manifests/init.pp | 87 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/files/exports diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/files/exports b/tools/devcloud/devcloudbox/puppet-devcloud/files/exports new file mode 100644 index 00000000000..55fdcfe9468 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/files/exports @@ -0,0 +1 @@ +/opt/storage/secondary *(rw,no_subtree_check,no_root_squash,fsid=0) diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp index b5d75b16425..9e1024d4b85 100644 --- a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp +++ b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp @@ -29,4 +29,91 @@ class puppet-devcloud { cwd => '/', } + package { 'nfs-server': + ensure => latest, + } + + file { '/opt/storage/secondary': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + type => 'directory', + } + + file { '/opt/storage/secondary/template/tmpl/1/1': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + type => 'directory', + } + + file { '/opt/storage/secondary/template/tmpl/1/5': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + type => 'directory', + } + + file { '/etc/exports': + require => Package['nfs-server'], + ensure => 'file', + source => 'puppet:///modules/puppet-devcloud/exports', + mode => '644', + owner => '0', + group => '0', + } + + service { 'nfs-kernel-server': + requires => Package['nfs-server'], + ensure => 'running', + enable => 'true', + } + + exec { "wget-default-template-1-vhd": + command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd http://download.cloud.com/templates/devcloud/defaulttemplates/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd", + creates => "/opt/storage/secondary/template/tmpl/1/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd", + requires => File['/opt/storage/secondary/template/tmpl/1/1'], + cwd => '/', + } + + exec { "wget-default-template-1-props": + command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/1/template.properties http://download.cloud.com/templates/devcloud/defaulttemplates/1/template.properties", + creates => "/opt/storage/secondary/template/tmpl/1/1/template.properties", + requires => File['/opt/storage/secondary/template/tmpl/1/1'], + cwd => '/', + } + + exec { "wget-default-template-5-vhd": + command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd http://download.cloud.com/templates/devcloud/defaulttemplates/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd", + creates => "/opt/storage/secondary/template/tmpl/1/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd", + requires => File['/opt/storage/secondary/template/tmpl/1/5'], + cwd => '/', + } + + exec { "wget-default-template-5-props": + command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/5/template.properties http://download.cloud.com/templates/devcloud/defaulttemplates/5/template.properties", + creates => "/opt/storage/secondary/template/tmpl/1/5/template.properties", + requires => File['/opt/storage/secondary/template/tmpl/1/5'], + cwd => '/', + } + + file { '/opt/storage/primary': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + type => 'directory', + } + + exec { "configlocal": + requires => File['/opt/storage/primary'], + unless => 'xe sr-list | grep local-storage', + command => "hostuuid=`xe host-list |grep uuid|awk '{print $5}'`; xe sr-create host-uuid=$hostuuid name-label=local-storage shared=false type=file device-config:location=/opt/storage/primary", + cwd => '/', + } + + } From 969b94e7dbc1033993e6991b97f64c38b0aef1e0 Mon Sep 17 00:00:00 2001 From: "chip.childers@gmail.com" Date: Mon, 30 Jul 2012 09:10:49 -0400 Subject: [PATCH 37/66] Adding license headers to puppet manifest files --- .../basebuild/puppet-devcloudinitial/init.pp | 17 +++++++++++++++++ .../puppet-devcloudinitial/manifests/init.pp | 17 +++++++++++++++++ .../devcloudbox/puppet-devcloud/init.pp | 17 +++++++++++++++++ .../puppet-devcloud/manifests/init.pp | 17 +++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/tools/devcloud/basebuild/puppet-devcloudinitial/init.pp b/tools/devcloud/basebuild/puppet-devcloudinitial/init.pp index bf70cec2580..213ef597008 100644 --- a/tools/devcloud/basebuild/puppet-devcloudinitial/init.pp +++ b/tools/devcloud/basebuild/puppet-devcloudinitial/init.pp @@ -1 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + include puppet-devcloudinitial diff --git a/tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp b/tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp index 8a0a9d011dc..a3c5c3d8855 100644 --- a/tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp +++ b/tools/devcloud/basebuild/puppet-devcloudinitial/manifests/init.pp @@ -1,3 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + class puppet-devcloudinitial { package { 'linux-headers-3.2.0-23-generic': diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/init.pp b/tools/devcloud/devcloudbox/puppet-devcloud/init.pp index c3922e39d30..2574392251a 100644 --- a/tools/devcloud/devcloudbox/puppet-devcloud/init.pp +++ b/tools/devcloud/devcloudbox/puppet-devcloud/init.pp @@ -1 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + include puppet-devcloud diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp index 9e1024d4b85..720927d1793 100644 --- a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp +++ b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp @@ -1,3 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + class puppet-devcloud { package { 'ebtables': From 236f63fd34a66eb6025731bad4def4c6f0f1ab5f Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 30 Jul 2012 15:07:03 +0200 Subject: [PATCH 38/66] When cleaning up or setting ip associations the NiciraNvpElement should be ignored. Implemented a generic ConnectivyProvider interface work around the dependency from server to nicira-plugin. --- .../network/element/ConnectivityProvider.java | 21 +++++++++++++++++++ .../network/element/NiciraNvpElement.java | 2 +- .../com/cloud/network/NetworkManagerImpl.java | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 api/src/com/cloud/network/element/ConnectivityProvider.java diff --git a/api/src/com/cloud/network/element/ConnectivityProvider.java b/api/src/com/cloud/network/element/ConnectivityProvider.java new file mode 100644 index 00000000000..81cac03ace7 --- /dev/null +++ b/api/src/com/cloud/network/element/ConnectivityProvider.java @@ -0,0 +1,21 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package com.cloud.network.element; + +public interface ConnectivityProvider extends NetworkElement { + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index ba4b9614520..ff9d020d7f3 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -90,7 +90,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.NicDao; @Local(value = NetworkElement.class) -public class NiciraNvpElement extends AdapterBase implements NetworkElement, NiciraNvpElementService, ResourceStateAdapter { +public class NiciraNvpElement extends AdapterBase implements ConnectivityProvider, NiciraNvpElementService, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(NiciraNvpElement.class); private static final Map> capabilities = setCapabilities(); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 83acc9b9c35..25565884728 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -126,6 +126,7 @@ import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; +import com.cloud.network.element.ConnectivityProvider; import com.cloud.network.element.DhcpServiceProvider; import com.cloud.network.element.FirewallServiceProvider; import com.cloud.network.element.IpDeployer; @@ -913,6 +914,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag deployer = ((PortForwardingServiceProvider) element).getIpDeployer(network); } else if (element instanceof RemoteAccessVPNServiceProvider) { deployer = ((RemoteAccessVPNServiceProvider) element).getIpDeployer(network); + } else if (element instanceof ConnectivityProvider) { + // Nothing to do + s_logger.debug("ConnectivityProvider " + element.getClass().getSimpleName() + " has no ip associations"); + continue; } else { throw new CloudRuntimeException("Fail to get ip deployer for element: " + element); } From b4bcd7f3fe1ade1e4db745ad959b9e1e3493e585 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 30 Jul 2012 15:07:48 +0200 Subject: [PATCH 39/66] Use the name of the network (or uuid) as display text of the nicira logical switch. --- .../com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java | 6 +++--- .../src/com/cloud/network/resource/NiciraNvpResource.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java index 3bac88b6b97..6cafe36b655 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java @@ -160,9 +160,9 @@ public class NiciraNvpGuestNetworkGuru extends GuestNetworkGuru { } // Name is either the given name or the uuid - String name = implemented.getName(); + String name = network.getName(); if (name == null || name.isEmpty()) { - name = implemented.getUuid(); + name = ((NetworkVO)network).getUuid(); } if (name.length() > 40 ) { name = name.substring(0, 39); // max length 40 @@ -179,7 +179,7 @@ public class NiciraNvpGuestNetworkGuru extends GuestNetworkGuru { String transportzoneuuid = niciraNvpHost.getDetail("transportzoneuuid"); String transportzoneisotype = niciraNvpHost.getDetail("transportzoneisotype"); - CreateLogicalSwitchCommand cmd = new CreateLogicalSwitchCommand(transportzoneuuid, transportzoneisotype, network.getName(), + CreateLogicalSwitchCommand cmd = new CreateLogicalSwitchCommand(transportzoneuuid, transportzoneisotype, name, context.getDomain().getName() + "-" + context.getAccount().getAccountName()); CreateLogicalSwitchAnswer answer = (CreateLogicalSwitchAnswer) _agentMgr.easySend(niciraNvpHost.getId(), cmd); diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java index ae7b37e6edb..69fd26f0d86 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java @@ -170,7 +170,7 @@ public class NiciraNvpResource implements ServerResource { private Answer executeRequest(CreateLogicalSwitchCommand cmd) { LogicalSwitch logicalSwitch = new LogicalSwitch(); - logicalSwitch.setDisplay_name("lswitch-" + cmd.getOwnerName()); + logicalSwitch.setDisplay_name("lswitch-" + cmd.getName()); logicalSwitch.setPort_isolation_enabled(false); // Set transport binding From 5d31b58c1b54d0d496f36d710bd04a3a17d40124 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 30 Jul 2012 15:11:03 +0200 Subject: [PATCH 40/66] Disable IPv6 in the systemvm --- patches/systemvm/debian/config/etc/sysctl.conf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/patches/systemvm/debian/config/etc/sysctl.conf b/patches/systemvm/debian/config/etc/sysctl.conf index 71b90f08d2a..7f945b0d4b1 100644 --- a/patches/systemvm/debian/config/etc/sysctl.conf +++ b/patches/systemvm/debian/config/etc/sysctl.conf @@ -40,3 +40,10 @@ net.ipv4.netfilter.ip_conntrack_max=1000000 net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_max_tw_buckets=1000000 net.core.somaxconn=1000000 + +# Disable IPv6 +net.ipv6.conf.all.disable_ipv6 = 1 +net.ipv6.conf.all.forwarding = 0 +net.ipv6.conf.all.accept_ra = 0 +net.ipv6.conf.all.accept_redirects = 0 +net.ipv6.conf.all.autoconf = 0 From 048bd2e498d6856f0919ec48013422f9551940dd Mon Sep 17 00:00:00 2001 From: David Nalley Date: Mon, 30 Jul 2012 10:32:07 -0400 Subject: [PATCH 41/66] fixing copyright notices on apidocs --- setup/apidoc/generateadmincommands.xsl | 5 +++-- setup/apidoc/generatecommand.xsl | 5 ++++- setup/apidoc/generatedomainadmincommands.xsl | 5 +++-- setup/apidoc/generatetoc_footer.xsl | 4 +++- setup/apidoc/generateusercommands.xsl | 5 +++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/setup/apidoc/generateadmincommands.xsl b/setup/apidoc/generateadmincommands.xsl index cf617190689..daaf010c2c0 100644 --- a/setup/apidoc/generateadmincommands.xsl +++ b/setup/apidoc/generateadmincommands.xsl @@ -124,8 +124,9 @@ version="1.0"> - - - -
diff --git a/setup/apidoc/generatecommand.xsl b/setup/apidoc/generatecommand.xsl index 1e44bc609da..0d2e8622711 100644 --- a/setup/apidoc/generatecommand.xsl +++ b/setup/apidoc/generatecommand.xsl @@ -167,19 +167,7 @@ version="1.0"> - - - -
diff --git a/setup/apidoc/generatedomainadmincommands.xsl b/setup/apidoc/generatedomainadmincommands.xsl index 7e1b5e858b4..f7e560c7680 100644 --- a/setup/apidoc/generatedomainadmincommands.xsl +++ b/setup/apidoc/generatedomainadmincommands.xsl @@ -131,19 +131,7 @@ version="1.0"> Apache and the Apache feather logo are trademarks of The Apache Software Foundation.

- - - -
diff --git a/setup/apidoc/generatetoc_footer.xsl b/setup/apidoc/generatetoc_footer.xsl index 6ebf1eef953..5bc2cf46659 100644 --- a/setup/apidoc/generatetoc_footer.xsl +++ b/setup/apidoc/generatetoc_footer.xsl @@ -13,19 +13,6 @@ Apache and the Apache feather logo are trademarks of The Apache Software Foundation.

- - - - -
diff --git a/setup/apidoc/generateusercommands.xsl b/setup/apidoc/generateusercommands.xsl index 9baf1b82f2f..3ec3a62c425 100644 --- a/setup/apidoc/generateusercommands.xsl +++ b/setup/apidoc/generateusercommands.xsl @@ -129,19 +129,7 @@ version="1.0"> Apache and the Apache feather logo are trademarks of The Apache Software Foundation.

- - - -
From 10e4a5ae4847ec7052d620b96f3fcd2263207c8e Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 30 Jul 2012 17:26:33 +0200 Subject: [PATCH 43/66] Disable IPv6 in XenServer if it is enabled. The cloud support pack apparently enables IPv6 support at the moment, but wihtout proper security. --- scripts/vm/hypervisor/xenserver/setupxenserver.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/vm/hypervisor/xenserver/setupxenserver.sh b/scripts/vm/hypervisor/xenserver/setupxenserver.sh index d3ade09c757..57456b3926c 100755 --- a/scripts/vm/hypervisor/xenserver/setupxenserver.sh +++ b/scripts/vm/hypervisor/xenserver/setupxenserver.sh @@ -23,6 +23,20 @@ usage() { } +if [ ! -f "/etc/modprobe.d/disable-ipv6" ] ; then + # disable IPv6 until reboot + if [ -d "/proc/sys/net/ipv6/conf/all" ] ; then + /sbin/sysctl -w net.ipv6.conf.all.forwarding=0 + /sbin/sysctl -w net.ipv6.conf.all.accept_ra=0 + /sbin/sysctl -w net.ipv6.conf.all.accept_redirects=0 + /sbin/sysctl -w net.ipv6.conf.all.autoconf=0 + /sbin/sysctl -w net.ipv6.conf.all.disable_ipv6=1 + fi + + # reinstate the disable-ipv6 file + echo "alias ipv6 no" > /etc/modprobe.d/disable-ipv6 + echo "alias net-pf-10 off" >> /etc/modprobe.d/disable-ipv6 +fi #removing iptables entry for vnc ports iptables -D RH-Firewall-1-INPUT -p tcp -m tcp --dport 5900:6099 -j ACCEPT 2>&1 From 4507df088d9b3b280298f16d13921e3c9498a7e8 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 30 Jul 2012 10:43:17 -0700 Subject: [PATCH 44/66] Fix positioning of tags error labels --- ui/css/cloudstack3.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 876d6633530..378c715cd24 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -9011,8 +9011,8 @@ div.panel.ui-dialog div.list-view div.fixed-header { .tagger form label.error { position: absolute; color: #FF0000; - left: 42px; - top: 29px; + left: 44px; + top: 28px !important; /*[empty]background-color:;*/ } From 372568cb9a394179d3f5d116a23f43e68e04dc6a Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 30 Jul 2012 10:46:09 -0700 Subject: [PATCH 45/66] CS-15743: disable static nat as a part of network resources cleanup Conflicts: server/src/com/cloud/network/NetworkManagerImpl.java server/src/com/cloud/network/rules/RulesManagerImpl.java --- .../com/cloud/network/NetworkManagerImpl.java | 6 ++ .../com/cloud/network/rules/RulesManager.java | 9 +++ .../cloud/network/rules/RulesManagerImpl.java | 72 ++++++++++++++----- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 25565884728..5a2b0176cff 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -5692,6 +5692,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag success = false; } + //release all static nats for the network + if (!_rulesMgr.applyStaticNatForNetwork(networkId, false, caller, true)) { + s_logger.warn("Failed to disable static nats as part of shutdownNetworkRules for network id " + networkId); + success = false; + } + // Get all ip addresses, mark as releasing and release them on the backend Network network = getNetwork(networkId); List userIps = _ipAddressDao.listByAssociatedNetwork(networkId, null); diff --git a/server/src/com/cloud/network/rules/RulesManager.java b/server/src/com/cloud/network/rules/RulesManager.java index 072cfc9f2d5..4b83e04eb28 100644 --- a/server/src/com/cloud/network/rules/RulesManager.java +++ b/server/src/com/cloud/network/rules/RulesManager.java @@ -78,4 +78,13 @@ public interface RulesManager extends RulesService { boolean disableStaticNat(long ipAddressId, Account caller, long callerUserId, boolean releaseIpIfElastic) throws ResourceUnavailableException; + /** + * @param networkId + * @param continueOnError + * @param caller + * @param forRevoke + * @return + */ + boolean applyStaticNatForNetwork(long networkId, boolean continueOnError, Account caller, boolean forRevoke); + } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index b45443e467c..d00835e0e64 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -1173,13 +1173,58 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { @Override public boolean applyStaticNatForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) { - - List staticNats = new ArrayList(); IpAddress sourceIp = _ipAddressDao.findById(sourceIpId); + + List staticNats = createStaticNatForIp(sourceIp, caller, forRevoke); + if (staticNats != null && !staticNats.isEmpty()) { + try { + if (!_networkMgr.applyStaticNats(staticNats, continueOnError)) { + return false; + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to create static nat rule due to ", ex); + return false; + } + } + + return true; + } + + + @Override + public boolean applyStaticNatForNetwork(long networkId, boolean continueOnError, Account caller, boolean forRevoke) { + List staticNatIps = _ipAddressDao.listStaticNatPublicIps(networkId); + + List staticNats = new ArrayList(); + for (IpAddress staticNatIp : staticNatIps) { + staticNats.addAll(createStaticNatForIp(staticNatIp, caller, forRevoke)); + } + + if (staticNats != null && !staticNats.isEmpty()) { + if (forRevoke) { + s_logger.debug("Found " + staticNats.size() + " static nats to disable for network id " + networkId); + } + try { + if (!_networkMgr.applyStaticNats(staticNats, continueOnError)) { + return false; + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to create static nat rule due to ", ex); + return false; + } + } else { + s_logger.debug("Found 0 static nat rules to apply for network id " + networkId); + } + + return true; + } + + protected List createStaticNatForIp(IpAddress sourceIp, Account caller, boolean forRevoke) { + List staticNats = new ArrayList(); if (!sourceIp.isOneToOneNat()) { - s_logger.debug("Source ip id=" + sourceIpId + " is not one to one nat"); - return true; + s_logger.debug("Source ip id=" + sourceIp + " is not one to one nat"); + return staticNats; } Long networkId = sourceIp.getAssociatedWithNetworkId(); @@ -1190,8 +1235,8 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { UserVmVO vm = _vmDao.findById(sourceIp.getAssociatedWithVmId()); Network network = _networkMgr.getNetwork(networkId); if (network == null) { - CloudRuntimeException ex = new CloudRuntimeException("Unable to find an ip address to map to specified vm id"); - ex.addProxyObject(vm, vm.getId(), "vmId"); + CloudRuntimeException ex = new CloudRuntimeException("Unable to find an ip address to map to specified vm id"); + ex.addProxyObject(vm, vm.getId(), "vmId"); throw ex; } @@ -1209,19 +1254,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { dstIp = _networkMgr.getIpInNetwork(sourceIp.getAssociatedWithVmId(), networkId); } - StaticNatImpl staticNat = new StaticNatImpl(sourceIp.getAllocatedToAccountId(), sourceIp.getAllocatedInDomainId(), networkId, sourceIpId, dstIp, forRevoke); + StaticNatImpl staticNat = new StaticNatImpl(sourceIp.getAllocatedToAccountId(), sourceIp.getAllocatedInDomainId(), + networkId, sourceIp.getId(), dstIp, forRevoke); staticNats.add(staticNat); - - try { - if (!_networkMgr.applyStaticNats(staticNats, continueOnError)) { - return false; - } - } catch (ResourceUnavailableException ex) { - s_logger.warn("Failed to create static nat rule due to ", ex); - return false; - } - - return true; + return staticNats; } @Override From 2b1feadb200c2eadf43c76a3531d2b0a9728bf96 Mon Sep 17 00:00:00 2001 From: "chip.childers@gmail.com" Date: Mon, 30 Jul 2012 15:30:25 -0400 Subject: [PATCH 46/66] Additional puppet configuration updates for devcloud. --- tools/devcloud/devcloudbox/Vagrantfile | 16 +- .../puppet-devcloud/files/configebtables.sh | 21 ++ .../files/configlocalstorage.sh | 25 ++ .../puppet-devcloud/files/configvnc.sh | 25 ++ .../puppet-devcloud/files/updatecode.sh | 27 +++ .../puppet-devcloud/manifests/init.pp | 226 +++++++++++++++--- 6 files changed, 303 insertions(+), 37 deletions(-) create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/files/configebtables.sh create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/files/configlocalstorage.sh create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/files/configvnc.sh create mode 100644 tools/devcloud/devcloudbox/puppet-devcloud/files/updatecode.sh diff --git a/tools/devcloud/devcloudbox/Vagrantfile b/tools/devcloud/devcloudbox/Vagrantfile index 6138926bab9..121a9f58a94 100644 --- a/tools/devcloud/devcloudbox/Vagrantfile +++ b/tools/devcloud/devcloudbox/Vagrantfile @@ -27,7 +27,7 @@ Vagrant::Config.run do |config| # Uncomment this line to enable the console for debugging the # build process. - config.vm.boot_mode = :gui + # config.vm.boot_mode = :gui # Setup port forwarding config.vm.forward_port 22, 2222 @@ -40,12 +40,12 @@ Vagrant::Config.run do |config| # Ensure the VM has the right virtual resources #config.vm. -# config.vm.provision :puppet do |puppet| -# puppet.manifests_path = "puppet-devcloud" -# puppet.manifest_file = "init.pp" -# puppet.with_ssh = true -# puppet.pp_path = "/etc/puppet" -# puppet.module_path = "puppet-devcloud" -# end + config.vm.provision :puppet do |puppet| + puppet.manifests_path = "puppet-devcloud" + puppet.manifest_file = "init.pp" + puppet.with_ssh = true + puppet.pp_path = "/etc/puppet" + puppet.module_path = "puppet-devcloud" + end end diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/files/configebtables.sh b/tools/devcloud/devcloudbox/puppet-devcloud/files/configebtables.sh new file mode 100644 index 00000000000..741884ee665 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/files/configebtables.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +mac=`/sbin/ifconfig xenbr0 |/bin/grep HWaddr |/usr/bin/awk '{print $5}'` +/sbin/ebtables -I FORWARD -d ! $mac -i eth0 -p IPV4 --ip-prot udp --ip-dport 67:68 -j DROP +exit 0 diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/files/configlocalstorage.sh b/tools/devcloud/devcloudbox/puppet-devcloud/files/configlocalstorage.sh new file mode 100644 index 00000000000..ab47d2dad4f --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/files/configlocalstorage.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +/usr/bin/xe sr-list | /bin/grep local-storage +rc=$? +if [[ $rc != 0 ]] ; then + hostuuid=`xe host-list |grep uuid|awk '{print $5}'`; + xe sr-create host-uuid=$hostuuid name-label=local-storage shared=false type=file device-config:location=/opt/storage/primary +fi +exit 0 diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/files/configvnc.sh b/tools/devcloud/devcloudbox/puppet-devcloud/files/configvnc.sh new file mode 100644 index 00000000000..b13a7a307ab --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/files/configvnc.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +grep 0.0.0.0 /usr/lib/xcp/lib/vncterm-wrapper +rc=$? +if [[ $rc != 0 ]] ; then + sed -i 's/VNCTERM_LISTEN=.\+/VNCTERM_LISTEN="-v 0.0.0.0:1"/' /usr/lib/xcp/lib/vncterm-wrapper +fi +exit 0 diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/files/updatecode.sh b/tools/devcloud/devcloudbox/puppet-devcloud/files/updatecode.sh new file mode 100644 index 00000000000..15e191aacb9 --- /dev/null +++ b/tools/devcloud/devcloudbox/puppet-devcloud/files/updatecode.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +cd /opt/cloudstack +git clone https://git-wip-us.apache.org/repos/asf/incubator-cloudstack.git +rc=$? +if [[ $rc != 0 ]] ; then + cd /opt/cloudstack/incubator-cloudstack + git pull origin master +fi +exit 0 diff --git a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp index 720927d1793..96f931db68e 100644 --- a/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp +++ b/tools/devcloud/devcloudbox/puppet-devcloud/manifests/init.pp @@ -40,22 +40,62 @@ class puppet-devcloud { owner => '0', } - exec { "mac=`ifconfig xenbr0 |grep HWaddr |awk '{print $5}'`; /sbin/ebtables -I FORWARD -d ! $mac -i eth0 -p IPV4 --ip-prot udp --ip-dport 67:68 -j DROP": + file { '/tmp/configebtables.sh': + ensure => 'file', + source => 'puppet:///modules/puppet-devcloud/configebtables.sh', + group => '0', + mode => '777', + owner => '0', + } + + exec { "/tmp/configebtables.sh": + require => [ + File['/tmp/configebtables.sh'], + Service['ebtables'] + ], subscribe => Package['ebtables'], refreshonly => true, cwd => '/', + path => '/sbin/:/usr/bin/:/bin', } package { 'nfs-server': ensure => latest, } + file { '/opt/storage': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + } + file { '/opt/storage/secondary': ensure => 'directory', group => '0', mode => '755', owner => '0', - type => 'directory', + } + + file { '/opt/storage/secondary/template': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + } + + file { '/opt/storage/secondary/template/tmpl': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + } + + file { '/opt/storage/secondary/template/tmpl/1': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', } file { '/opt/storage/secondary/template/tmpl/1/1': @@ -63,7 +103,6 @@ class puppet-devcloud { group => '0', mode => '755', owner => '0', - type => 'directory', } file { '/opt/storage/secondary/template/tmpl/1/5': @@ -71,7 +110,6 @@ class puppet-devcloud { group => '0', mode => '755', owner => '0', - type => 'directory', } file { '/etc/exports': @@ -84,37 +122,40 @@ class puppet-devcloud { } service { 'nfs-kernel-server': - requires => Package['nfs-server'], + require => Package['nfs-server'], ensure => 'running', enable => 'true', } - exec { "wget-default-template-1-vhd": - command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd http://download.cloud.com/templates/devcloud/defaulttemplates/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd", - creates => "/opt/storage/secondary/template/tmpl/1/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd", - requires => File['/opt/storage/secondary/template/tmpl/1/1'], - cwd => '/', + exec { '/usr/bin/wget http://download.cloud.com/templates/devcloud/defaulttemplates/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd -P /opt/storage/secondary/template/tmpl/1/1/': + creates => '/opt/storage/secondary/template/tmpl/1/1/dc68eb4c-228c-4a78-84fa-b80ae178fbfd.vhd', + require => File['/opt/storage/secondary/template/tmpl/1/1/'], + timeout => '0', } - exec { "wget-default-template-1-props": - command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/1/template.properties http://download.cloud.com/templates/devcloud/defaulttemplates/1/template.properties", - creates => "/opt/storage/secondary/template/tmpl/1/1/template.properties", - requires => File['/opt/storage/secondary/template/tmpl/1/1'], - cwd => '/', + exec { '/usr/bin/wget http://download.cloud.com/templates/devcloud/defaulttemplates/1/template.properties -P /opt/storage/secondary/template/tmpl/1/1/': + creates => '/opt/storage/secondary/template/tmpl/1/1/template.properties', + require => File['/opt/storage/secondary/template/tmpl/1/1/'], } - exec { "wget-default-template-5-vhd": - command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd http://download.cloud.com/templates/devcloud/defaulttemplates/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd", - creates => "/opt/storage/secondary/template/tmpl/1/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd", - requires => File['/opt/storage/secondary/template/tmpl/1/5'], - cwd => '/', + exec { '/usr/bin/wget http://download.cloud.com/templates/devcloud/defaulttemplates/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd -P /opt/storage/secondary/template/tmpl/1/5/': + creates => '/opt/storage/secondary/template/tmpl/1/5/ce5b212e-215a-3461-94fb-814a635b2215.vhd', + require => File['/opt/storage/secondary/template/tmpl/1/5/'], + timeout => '0', } - exec { "wget-default-template-5-props": - command => "/usr/bin/wget --output-document=/opt/storage/secondary/template/tmpl/1/5/template.properties http://download.cloud.com/templates/devcloud/defaulttemplates/5/template.properties", - creates => "/opt/storage/secondary/template/tmpl/1/5/template.properties", - requires => File['/opt/storage/secondary/template/tmpl/1/5'], - cwd => '/', + exec { '/usr/bin/wget http://download.cloud.com/templates/devcloud/defaulttemplates/5/template.properties -P /opt/storage/secondary/template/tmpl/1/5/': + creates => '/opt/storage/secondary/template/tmpl/1/5/template.properties', + require => File['/opt/storage/secondary/template/tmpl/1/5/'], + } + + exec { 'getecho': + command => '/usr/bin/wget http://download.cloud.com/templates/devcloud/echo -P /usr/lib/xcp/plugins/', + creates => '/usr/lib/xcp/plugins/echo', + } + + exec { '/bin/chmod -R 777 /usr/lib/xcp': + require => Exec['getecho'], } file { '/opt/storage/primary': @@ -122,15 +163,142 @@ class puppet-devcloud { group => '0', mode => '755', owner => '0', - type => 'directory', + } + + file { '/tmp/configlocalstorage.sh': + ensure => 'file', + group => '0', + mode => '777', + owner => '0', + source => 'puppet:///modules/puppet-devcloud/configlocalstorage.sh', } exec { "configlocal": - requires => File['/opt/storage/primary'], - unless => 'xe sr-list | grep local-storage', - command => "hostuuid=`xe host-list |grep uuid|awk '{print $5}'`; xe sr-create host-uuid=$hostuuid name-label=local-storage shared=false type=file device-config:location=/opt/storage/primary", + require => [ + File['/opt/storage/primary'], + File['/tmp/configlocalstorage.sh'] + ], + command => '/tmp/configlocalstorage.sh', cwd => '/', } + file { '/tmp/configvnc.sh': + ensure => 'file', + source => 'puppet:///modules/puppet-devcloud/configvnc.sh', + mode => '777', + group => '0', + owner => '0', + } + + exec { "configvnc": + require => File['/tmp/configvnc.sh'], + command => '/tmp/configvnc.sh', + cwd => '/', + } + + package { 'git': + ensure => latest, + } + + package { 'unzip': + ensure => latest, + } + + package { 'mysql-server': + ensure => latest, + } + + package { 'ant': + ensure => latest, + } + + package { 'openjdk-6-jdk': + ensure => latest, + } + + file { '/opt/cloudstack': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + } + + file { '/tmp/updatecode.sh': + ensure => 'file', + source => 'puppet:///modules/puppet-devcloud/updatecode.sh', + mode => '777', + owner => '0', + group => '0', + } + + exec { 'get_code': + require => [ + Package['git'], + File['/opt/cloudstack/'], + File['/tmp/updatecode.sh'] + ], + command => '/tmp/updatecode.sh', + cwd => '/opt/cloudstack/', + timeout => '0', + } + + file { '/opt/cloudstack/incubator-cloudstack/target': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + require => Exec['get_code'], + } + + file { '/opt/cloudstack/incubator-cloudstack/dist': + ensure => 'directory', + group => '0', + mode => '755', + owner => '0', + require => Exec['get_code'], + } + + exec { 'downloadtomcat': + command => '/usr/bin/wget http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.32/bin/apache-tomcat-6.0.32.zip -P /opt/cloudstack/', + creates => '/opt/cloudstack/apache-tomcat-6.0.32.zip', + require => File['/opt/cloudstack/'], + timeout => '0', + } + + exec { "unziptomcat": + require => [ + Package['unzip'], + Exec["downloadtomcat"] + ], + creates => "/opt/cloudstack/apache-tomcat-6.0.32", + command => "/usr/bin/unzip apache-tomcat-6.0.32.zip", + cwd => "/opt/cloudstack", + timeout => '0', + } + + exec { "catalina_home": + require => Exec["unziptomcat"], + unless => '/bin/grep CATALINA_HOME /root/.bashrc', + command => '/bin/echo "export CATALINA_HOME=/opt/cloudstack/apache-tomcat-6.0.32" >> /root/.bashrc', + cwd => '/', + } + + exec { "build_cloudstack": + require => [ + Package['ant'], + Exec["catalina_home"], + File['/opt/cloudstack/incubator-cloudstack/dist'], + File['/opt/cloudstack/incubator-cloudstack/target'] + ], + command => "/usr/bin/ant clean-all build-all deploy-server deploydb", + cwd => "/opt/cloudstack/incubator-cloudstack/", + timeout => '0', + } + +# exec { "start_cloudstack": +# require => Exec["build_cloudstack"], +# command => "/usr/bin/ant debug", +# cwd => "/opt/cloudstack/incubator-cloudstack", +# } } From 9ec89b92400524993eb8cc998efde0e7dafdc883 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 30 Jul 2012 13:33:17 -0700 Subject: [PATCH 47/66] Allow EIP/ELB network creation only in Basic zone --- server/src/com/cloud/network/NetworkManagerImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 5a2b0176cff..4dd5eab388a 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2553,6 +2553,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Only Account specific Isolated network with sourceNat service disabled are allowed in security group enabled zone"); } } + + //don't allow eip/elb networks in Advance zone + if (ntwkOff.getElasticIp() || ntwkOff.getElasticLb()) { + throw new InvalidParameterValueException("Elastic IP and Elastic LB services are supported in zone of type " + NetworkType.Basic); + } } // VlanId can be specified only when network offering supports it From 36fc2bd9b5e2768a27287deaee381c0afc6734a0 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 31 Jul 2012 02:57:46 +0530 Subject: [PATCH 48/66] CS-15044:API changes and UI changes to provide option to view the name of the guestnetwork a virtual machine belongs --- .../com/cloud/api/response/NicResponse.java | 7 ++++ .../src/com/cloud/api/ApiResponseHelper.java | 1 + ui/scripts/instances.js | 32 +++++++++++++------ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/api/src/com/cloud/api/response/NicResponse.java b/api/src/com/cloud/api/response/NicResponse.java index 010cf4992e5..69d5c31f66c 100755 --- a/api/src/com/cloud/api/response/NicResponse.java +++ b/api/src/com/cloud/api/response/NicResponse.java @@ -29,6 +29,9 @@ public class NicResponse extends BaseResponse { @SerializedName("networkid") @Param(description="the ID of the corresponding network") private final IdentityProxy networkId = new IdentityProxy("networks"); + + @SerializedName("networkname") @Param(description="the name of the corresponding network") + private String networkName ; @SerializedName(ApiConstants.NETMASK) @Param(description="the netmask of the nic") private String netmask; @@ -69,6 +72,10 @@ public class NicResponse extends BaseResponse { this.networkId.setValue(networkid); } + public void setNetworkName(String networkname) { + this.networkName = networkname; + } + public void setNetmask(String netmask) { this.netmask = netmask; } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 433d2637e52..399a816bd0f 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1566,6 +1566,7 @@ public class ApiResponseHelper implements ResponseGenerator { nicResponse.setGateway(singleNicProfile.getGateway()); nicResponse.setNetmask(singleNicProfile.getNetmask()); nicResponse.setNetworkid(singleNicProfile.getNetworkId()); + nicResponse.setNetworkName(ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId()).getName()); if (acct.getType() == Account.ACCOUNT_TYPE_ADMIN) { if (singleNicProfile.getBroadCastUri() != null) { nicResponse.setBroadcastUri(singleNicProfile.getBroadCastUri().toString()); diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index bca405b2d5b..ede22e13b13 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -1185,6 +1185,7 @@ fields: [ { name: { label: 'label.name', header: true }, + networkname: {label: 'Network Name' }, ipaddress: { label: 'label.ip.address' }, type: { label: 'label.type' }, gateway: { label: 'label.gateway' }, @@ -1198,17 +1199,28 @@ } ], dataProvider: function(args) { - args.response.success({data: $.map(args.context.instances[0].nic, function(nic, index) { - var name = 'NIC ' + (index + 1); - - if (nic.isdefault) { - name += ' (' + _l('label.default') + ')'; - } - return $.extend(nic, { - name: name + $.ajax({ + url:createURL("listVirtualMachines&details=nics&id=" + args.context.instances[0].id), + dataType: "json", + async:true, + success:function(json) { + // Handling the display of network name for a VM under the NICS tabs + args.response.success({ + data: $.map(args.context.instances[0].nic, function(nic, index) { + var name = 'NIC ' + (index + 1); + var networkname = json.listvirtualmachinesresponse.virtualmachine[0].nic[index].networkname; + if (nic.isdefault) { + name += ' (' + _l('label.default') + ')'; + } + return $.extend(nic, { + name: name, + networkname: networkname + }); + }) + }); + } }); - })}); - } + } }, /** From 6b47907f3980efa899f606035245cde535454e1d Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 30 Jul 2012 14:29:47 -0700 Subject: [PATCH 49/66] CS-15726: Use custom validation for tagger widget Show a generic dialog box for tagger validation, instead of using jQuery validate --it conflicted with the detail view's edit fields and prevented submission unless the key and value fields were filled out. --- ui/scripts/ui/widgets/tagger.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ui/scripts/ui/widgets/tagger.js b/ui/scripts/ui/widgets/tagger.js index f671342c99c..c6169454cb2 100644 --- a/ui/scripts/ui/widgets/tagger.js +++ b/ui/scripts/ui/widgets/tagger.js @@ -1,13 +1,26 @@ (function($, cloudStack) { + var isFormValid = function($form) { + var key = $form.find('input[name=key]').val(); + var value = $form.find('input[name=value]').val(); + + if (!key || !value) { + cloudStack.dialog.notice({ message: 'Please specify a tag key and value' }); + + return false; + } + + return true; + }; + var elems = { inputArea: function(args) { var $form = $('
').addClass('tag-input'); var $keyField = $('
').addClass('field key'); var $keyLabel = $('