From 392d55dead6cf7825e96a4c9c25acc63bb40a651 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 May 2013 12:46:37 -0700 Subject: [PATCH 001/201] Add base VPC chart --- ui/modules/modules.js | 1 + ui/modules/vpc/vpc.css | 100 +++++++++++++++++++++++++++++++++++++++++ ui/modules/vpc/vpc.js | 70 +++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 ui/modules/vpc/vpc.css create mode 100644 ui/modules/vpc/vpc.js diff --git a/ui/modules/modules.js b/ui/modules/modules.js index 490749ff085..ee553fd1af2 100644 --- a/ui/modules/modules.js +++ b/ui/modules/modules.js @@ -16,5 +16,6 @@ // under the License. (function($, cloudStack) { cloudStack.modules = [ + 'vpc' ]; }(jQuery, cloudStack)); diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css new file mode 100644 index 00000000000..2022c22ff8b --- /dev/null +++ b/ui/modules/vpc/vpc.css @@ -0,0 +1,100 @@ +/*[fmt]1C20-1C0D-E*/ +/* +* 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. +*/ +.vpc-network-chart { +} + +.vpc-network-chart .tiers { +} + +.vpc-network-chart .tier-item { + border: 1px solid #477FB4; + overflow: hidden; + width: 326px; + height: 182px; + margin: 18px; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + background: #8DB1D3; +} + +.vpc-network-chart .tier-item .header { + padding: 7px 0 6px; + /*+box-shadow:inset 0px 1px 1px #FFFFFF;*/ + -moz-box-shadow: inset 0px 1px 1px #FFFFFF; + -webkit-box-shadow: inset 0px 1px 1px #FFFFFF; + -o-box-shadow: inset 0px 1px 1px #FFFFFF; + box-shadow: inset 0px 1px 1px #FFFFFF; + background: #69839D; + border-bottom: 1px solid #40639E; +} + +.vpc-network-chart .tier-item .header .title { + margin-left: 9px; + max-width: 268px; + overflow: hidden; +} + +.vpc-network-chart .tier-item .header .title span { + font-size: 20px; + color: #FFFFFF; + /*+text-shadow:0px 1px 1px #000000;*/ + -moz-text-shadow: 0px 1px 1px #000000; + -webkit-text-shadow: 0px 1px 1px #000000; + -o-text-shadow: 0px 1px 1px #000000; + text-shadow: 0px 1px 1px #000000; +} + +.vpc-network-chart .tier-item .content { + width: 100%; + height: 83%; + /*+box-shadow:inset 0px 1px 1px #FFFFFF;*/ + -moz-box-shadow: inset 0px 1px 1px #FFFFFF; + -webkit-box-shadow: inset 0px 1px 1px #FFFFFF; + -o-box-shadow: inset 0px 1px 1px #FFFFFF; + box-shadow: inset 0px 1px 1px #FFFFFF; + border-bottom: 1px solid #8DB1D3; +} + +.vpc-network-chart .tier-item .content .dashboard { + height: 117px; +} + +.vpc-network-chart .tier-item .content .info { + padding: 7px 0 10px 9px; +} + +.vpc-network-chart .tier-item .content .info .cidr-label { + font-size: 10px; + color: #1860A7; +} + +.vpc-network-chart .tier-item .content .info .cidr { + color: #364553; + font-size: 10px; + /*+text-shadow:0px 1px #C7D8E9;*/ + -moz-text-shadow: 0px 1px #C7D8E9; + -webkit-text-shadow: 0px 1px #C7D8E9; + -o-text-shadow: 0px 1px #C7D8E9; + text-shadow: 0px 1px #C7D8E9; +} + diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js new file mode 100644 index 00000000000..065a91de18e --- /dev/null +++ b/ui/modules/vpc/vpc.js @@ -0,0 +1,70 @@ +(function($, cloudStack) { + var elems = { + chart: { + tier: function(args) { + var tier = args.tier; + var $tier = $('
').addClass('tier-item'); + var $header = $('
').addClass('header'); + var $title = $('
').addClass('title').append($('')); + var $content = $('
').addClass('content'); + var $dashboard = $('
').addClass('dashboard'); + var $info = $('
').addClass('info'); + var $cidrLabel = $('').addClass('cidr-label'); + var $cidr = $('').addClass('cidr'); + + $cidrLabel.html('CIDR: '); + $cidr.html(tier.cidr); + $title.find('span').html(tier.displayname ? tier.displayname : tier.name); + $header.append($title); + $info.append($cidrLabel, $cidr); + $content.append($dashboard, $info); + $tier.append($header, $content); + + return $tier; + } + } + }; + + cloudStack.modules.vpc = function(module) { + var vpc = cloudStack.vpc; + var vpcSection = cloudStack.sections.network.sections.vpc; + var listConfigureAction = vpcSection.listView.actions.configureVpc.action; + var detailsConfigureAction = vpcSection.listView.detailView.actions.configureVpc.action; + + var vpcChart = function(args) { + var context = args.context; + var vpcItem = context.vpc[0]; + var $chart = $('
').addClass('vpc-network-chart'); + var $tiers = $('
').addClass('tiers'); + + $tiers.appendTo($chart); + + // Get tiers + vpc.tiers.dataProvider({ + context: context, + response: { + success: function(data) { + var tiers = data.tiers; + + $(tiers).map(function(index, tier) { + var $tier = elems.chart.tier({ tier: tier }); + + $tier.appendTo($tiers); + }); + } + } + }); + + $('#browser .container').cloudBrowser('addPanel', { + title: vpcItem.displaytext ? vpcItem.displaytext : vpcItem.name, + maximizeIfSelected: true, + complete: function($panel) { + $chart.appendTo($panel); + } + }); + }; + + listConfigureAction.custom = vpcChart; + detailsConfigureAction.custom = vpcChart; + }; +}(jQuery, cloudStack)); From fbefeea46109b138a6a5c4ae800b483acec89c98 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 May 2013 15:27:06 -0700 Subject: [PATCH 002/201] Add tier mini-dashboard --- ui/modules/vpc/vpc.css | 57 +++++++++++++++++++++++++++++- ui/modules/vpc/vpc.js | 80 +++++++++++++++++++++++++++++++----------- 2 files changed, 115 insertions(+), 22 deletions(-) diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css index 2022c22ff8b..f84cbf0aa8e 100644 --- a/ui/modules/vpc/vpc.css +++ b/ui/modules/vpc/vpc.css @@ -21,6 +21,8 @@ } .vpc-network-chart .tiers { + width: 362px; + float: right; } .vpc-network-chart .tier-item { @@ -79,8 +81,61 @@ height: 117px; } +.vpc-network-chart .tier-item .content .dashboard-item { + width: 145px; + height: 54px; + margin: 7px 9px 0; + background: #C1E0FE; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + float: left; + cursor: pointer; +} + +.vpc-network-chart .tier-item .content .dashboard-item:hover { + background-color: #DBEDFE; + /*+box-shadow:inset 0px 1px 2px #000000;*/ + -moz-box-shadow: inset 0px 1px 2px #000000; + -webkit-box-shadow: inset 0px 1px 2px #000000; + -o-box-shadow: inset 0px 1px 2px #000000; + box-shadow: inset 0px 1px 2px #000000; +} + +.vpc-network-chart .tier-item .content .dashboard-item .total { + font-size: 28px; + /*+placement:shift 7px 5px;*/ + position: relative; + left: 7px; + top: 5px; + color: #145CA1; + font-weight: 100; + /*+text-shadow:0px 1px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px 1px #FFFFFF; + -o-text-shadow: 0px 1px 1px #FFFFFF; + text-shadow: 0px 1px 1px #FFFFFF; +} + +.vpc-network-chart .tier-item .content .dashboard-item .name { + font-size: 11px; + text-transform: uppercase; + color: #0861B7; + /*+placement:shift 8px 7px;*/ + position: relative; + left: 8px; + top: 7px; + /*+text-shadow:0px 1px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px 1px #FFFFFF; + -o-text-shadow: 0px 1px 1px #FFFFFF; + text-shadow: 0px 1px 1px #FFFFFF; +} + .vpc-network-chart .tier-item .content .info { - padding: 7px 0 10px 9px; + padding: 9px 0 10px 10px; } .vpc-network-chart .tier-item .content .info .cidr-label { diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 065a91de18e..68f14191e78 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -1,27 +1,45 @@ (function($, cloudStack) { var elems = { - chart: { - tier: function(args) { - var tier = args.tier; - var $tier = $('
').addClass('tier-item'); - var $header = $('
').addClass('header'); - var $title = $('
').addClass('title').append($('')); - var $content = $('
').addClass('content'); - var $dashboard = $('
').addClass('dashboard'); - var $info = $('
').addClass('info'); - var $cidrLabel = $('').addClass('cidr-label'); - var $cidr = $('').addClass('cidr'); + tier: function(args) { + var tier = args.tier; + var dashboardItems = args.dashboardItems; + var $tier = $('
').addClass('tier-item'); + var $header = $('
').addClass('header'); + var $title = $('
').addClass('title').append($('')); + var $content = $('
').addClass('content'); + var $dashboard = elems.dashboard({ + dashboardItems: dashboardItems + }); + var $info = $('
').addClass('info'); + var $cidrLabel = $('').addClass('cidr-label'); + var $cidr = $('').addClass('cidr'); - $cidrLabel.html('CIDR: '); - $cidr.html(tier.cidr); - $title.find('span').html(tier.displayname ? tier.displayname : tier.name); - $header.append($title); - $info.append($cidrLabel, $cidr); - $content.append($dashboard, $info); - $tier.append($header, $content); + $cidrLabel.html('CIDR: '); + $cidr.html(tier.cidr); + $title.find('span').html(tier.displayname ? tier.displayname : tier.name); + $header.append($title); + $info.append($cidrLabel, $cidr); + $content.append($dashboard, $info); + $tier.append($header, $content); - return $tier; - } + return $tier; + }, + + dashboard: function(args) { + var $dashboard = $('
').addClass('dashboard'); + + $(args.dashboardItems).map(function(index, dashboardItem) { + var $dashboardItem = $('
').addClass('dashboard-item'); + var $name = $('
').addClass('name').append($('')); + var $total = $('
').addClass('total').append($('')); + + $name.find('span').html(dashboardItem.name); + $total.find('span').html(dashboardItem.total); + $dashboardItem.append($total, $name); + $dashboardItem.appendTo($dashboard); + }); + + return $dashboard; } }; @@ -47,7 +65,27 @@ var tiers = data.tiers; $(tiers).map(function(index, tier) { - var $tier = elems.chart.tier({ tier: tier }); + var $tier = elems.tier({ + tier: tier, + dashboardItems: [ + { + name: 'Load balancers', + total: 5 + }, + { + name: 'Port forwarders', + total: 4 + }, + { + name: 'Static NATs', + total: 3 + }, + { + name: 'Virtual Machines', + total: 300 + } + ] + }); $tier.appendTo($tiers); }); From 3c9632814ad21b741343e1252438ab96d860df65 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 May 2013 15:44:28 -0700 Subject: [PATCH 003/201] UI plugin API: Support IE-compatible CSS loading If browser is IE < 9, use document.createStyleSheet to properly load plugin's CSS dynamically. --- ui/scripts/plugins.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ui/scripts/plugins.js b/ui/scripts/plugins.js index 122f4a03491..6a886ba0ae6 100644 --- a/ui/scripts/plugins.js +++ b/ui/scripts/plugins.js @@ -20,15 +20,20 @@ } var loadCSS = function(path) { - var $link = $(''); + if (document.createStyleSheet) { + // IE-compatible CSS loading + document.createStyleSheet(path); + } else { + var $link = $(''); - $link.attr({ - rel: 'stylesheet', - type: 'text/css', - href: path - }); + $link.attr({ + rel: 'stylesheet', + type: 'text/css', + href: path + }); - $('head').append($link); + $('html head').append($link); + } }; $.extend(cloudStack.pluginAPI, { From 9c68b09376df5c98c4e5001840acd25f61a1c3a0 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 May 2013 15:44:41 -0700 Subject: [PATCH 004/201] Add tier placeholder box --- ui/modules/vpc/vpc.css | 45 ++++++++++++++++++++++++++++++++++++++++++ ui/modules/vpc/vpc.js | 11 +++++++++++ 2 files changed, 56 insertions(+) diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css index f84cbf0aa8e..d5ad6b21c25 100644 --- a/ui/modules/vpc/vpc.css +++ b/ui/modules/vpc/vpc.css @@ -21,6 +21,7 @@ } .vpc-network-chart .tiers { + margin: 40px 46px 0 0; width: 362px; float: right; } @@ -153,3 +154,47 @@ text-shadow: 0px 1px #C7D8E9; } +.vpc-network-chart .tier-placeholder { + cursor: pointer; + background: #EFEFEF; + border: 4px dotted #B1B1B1; + /*+border-radius:8px;*/ + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + -khtml-border-radius: 8px; + border-radius: 8px; + width: 325px; + text-align: center; + padding: 57px 0 55px; + margin: 0 0 0 18px; +} + +.vpc-network-chart .tier-placeholder:hover { + background: #DCDCDC; + /*+border-radius:8px;*/ + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + -khtml-border-radius: 8px; + border-radius: 8px; + /*+box-shadow:inset 0px 1px 4px #000000;*/ + -moz-box-shadow: inset 0px 1px 4px #000000; + -webkit-box-shadow: inset 0px 1px 4px #000000; + -o-box-shadow: inset 0px 1px 4px #000000; + box-shadow: inset 0px 1px 4px #000000; + /*+text-shadow:0px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px #FFFFFF; + -o-text-shadow: 0px 1px #FFFFFF; + text-shadow: 0px 1px #FFFFFF; +} + +.vpc-network-chart .tier-placeholder:hover span { + color: #535353; +} + +.vpc-network-chart .tier-placeholder span { + color: #AFAFAF; + font-size: 24px; + font-weight: 200; +} + diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 68f14191e78..ee9e1485f1a 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -25,6 +25,14 @@ return $tier; }, + tierPlaceholder: function() { + var $placeholder = $('
').addClass('tier-placeholder'); + + $placeholder.append($('').append('Create network')); + + return $placeholder; + }, + dashboard: function(args) { var $dashboard = $('
').addClass('dashboard'); @@ -89,6 +97,9 @@ $tier.appendTo($tiers); }); + + // Add placeholder tier + $tiers.append(elems.tierPlaceholder()); } } }); From f9b843d7449a1466ebb0f6f86e0c8b567206a713 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 May 2013 16:11:45 -0700 Subject: [PATCH 005/201] Add tier 'view all' icon --- ui/images/sprites.png | Bin 192407 -> 192511 bytes ui/modules/vpc/vpc.css | 40 +++++++++++++++++++++++++++++++++++++--- ui/modules/vpc/vpc.js | 3 ++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/ui/images/sprites.png b/ui/images/sprites.png index 132588d10049a3d4058d35ba137015ac988fa27d..2c30b581cc4c7c338a39b128cd0b796e98da2968 100644 GIT binary patch delta 157782 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�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 IM6N<$g3Y@r=Kufz delta 157239 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').addClass('detail-link'); var $info = $('

').addClass('info'); var $cidrLabel = $('').addClass('cidr-label'); var $cidr = $('').addClass('cidr'); @@ -17,7 +18,7 @@ $cidrLabel.html('CIDR: '); $cidr.html(tier.cidr); $title.find('span').html(tier.displayname ? tier.displayname : tier.name); - $header.append($title); + $header.append($title, $detailLink); $info.append($cidrLabel, $cidr); $content.append($dashboard, $info); $tier.append($header, $content); From 22a546628910a46b6bdbaee7f63250d30e20e966 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 May 2013 16:27:03 -0700 Subject: [PATCH 006/201] WIP: VPC router chart item --- ui/modules/vpc/vpc.css | 46 ++++++++++++++++++++++++++++++++++++++++++ ui/modules/vpc/vpc.js | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css index 95f01111357..f6ede66bd9b 100644 --- a/ui/modules/vpc/vpc.css +++ b/ui/modules/vpc/vpc.css @@ -18,6 +18,9 @@ * under the License. */ .vpc-network-chart { + width: 100%; + height: 100%; + overflow: auto; } .vpc-network-chart .tiers { @@ -232,3 +235,46 @@ font-weight: 200; } +.vpc-network-chart .tier-item.router { + width: 258px; + height: 218px; + background: #BDBDBD; + border: 1px solid #808080; + float: left; + /*+placement:shift 10px 176px;*/ + position: relative; + left: 10px; + top: 176px; +} + +.vpc-network-chart .tier-item.router .header { + background: #908F8F; + padding: 15px 0 14px; + border-bottom: 1px solid #808080; +} + +.vpc-network-chart .tier-item.router .header .title { + width: 212px; +} + +.vpc-network-chart .tier-item.router .header .title span { + padding: 0 0 0 32px; +} + +.vpc-network-chart .tier-item.router .dashboard-item { + width: 100px; + /*[empty]margin:;*/ + padding: 0px 2px 0px 6px; + height: 73px; + background: #A7A7A7; +} + +.vpc-network-chart .tier-item.router .dashboard-item span { + color: #FFFFFF; + /*+text-shadow:0px 1px #000000;*/ + -moz-text-shadow: 0px 1px #000000; + -webkit-text-shadow: 0px 1px #000000; + -o-text-shadow: 0px 1px #000000; + text-shadow: 0px 1px #000000; +} + diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 69cf795252b..4a3d6493aa5 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -26,6 +26,19 @@ return $tier; }, + router: function(args) { + var $router = elems.tier({ + tier: { + name: 'Router', + }, + dashboardItems: args.dashboardItems + }).addClass('router'); + + $router.find('.info').remove(); + + return $router; + }, + tierPlaceholder: function() { var $placeholder = $('
').addClass('tier-placeholder'); @@ -104,6 +117,28 @@ } } }); + + // Router + $router = elems.router({ + dashboardItems: [ + { + name: 'Private gateways', + total: 1 + }, + { + name: 'Public IP addresses', + total: 2 + }, + { + name: 'Site-to-site VPNs', + total: 3 + }, + { + name: 'Network ACL lists', + total: 2 + } + ] + }).appendTo($chart); $('#browser .container').cloudBrowser('addPanel', { title: vpcItem.displaytext ? vpcItem.displaytext : vpcItem.name, From 34774c0c30d52ecc7828ffe6252f57eced75400c Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 8 May 2013 14:03:51 -0700 Subject: [PATCH 007/201] WIP --- ui/images/sprites.png | Bin 192511 -> 194177 bytes ui/modules/vpc/vpc.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/images/sprites.png b/ui/images/sprites.png index 2c30b581cc4c7c338a39b128cd0b796e98da2968..156df1ae30d6f813272804c48642f5af8da00af5 100644 GIT binary patch delta 94752 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%0D)Rr6|U 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 Ce!a^8 delta 92646 zcmagGby!qi)IWNLmQD$2m6lK%gdzNb$N&-ol7a{b2#P~UoS{JkR8qQz5Ew!M=@g_p zlm_YU9_|6(-+Q0?$G!J?e0b!<-g~XR*7|(bTKnL$PI56tQdCEbGtcMOKwREH46Awv z29VW%R(M0L>>IK>xU0^cljFwvE{Lw+-yghA`^W6EYa*tJmV=l2qt*1FgJ zcALz&dxN_B>OJ;}6Td??WA!DP>@{8Wk%*Bhc}?l?pMqRXC9lPg!PoDm%u~dL{y%c93_g9Lq~aK-YB^icRA2KdN_yo$yf}-(5_%& zORK`~Q&TtLx@Dj6={RO7$!|ES%F4=-(Ugkdpz-Pcu0P%R`VApNTAjG$ivMVE_FuMiwSrhN0s9C-gbHUpSM zejod{gU`!fTD!u)(LwxHvaAP>S=mkCZ4G*gS;T3_Bvf_;>}RhcICNC(kPIkkaMxhN z7k0TJT=!VuT_j`gdcO!N^5VPQuK$*nIY-#Q%LpKey71nT^eXlG!yU7T05L!m_46C$AdA1IIl%=qe%$T~3u z>^3LSTKxo>EO_uS3KaN~m;l~I}tn1K~x&R0YfP8TrA%F{U|J(6teKX zy++`2e?+^At~N6ZPt0EF=SZ%`hpmHuL)}s8)g9G;op{=H^`Op&#GQ_3+T{pNd7FziRmvj%z4@T=)05(5RF)E4AvbqOQUGi}<=$&J$N%SA9YD_M zqfA=@|5uGEjGA!uKJ>J5QFN2wzq^HNLFT^Cp8@gLc&?=Zx4-jNTrcWXhuZ1PmPa}#+|K>Q@V|_wl z60yReF!orJP*@w-)-uh(4o%2Zq4^&t;3SSRf*IqcE=z8-5Nz?FF3vsEw*JkU9-1l;CqrVgQ+@>z5r4!>iBF*f-5j9(UWo0|>WHAL zzjr1nYC(nQIXL|D{zcw^}Rc zxk~8fzEyNhf9El?e~@1JmH6~v%>+PQ`KV3$=YX@EiP)WL5s%5MT~(&x_#XDGT=t)+ zb6xiT%&TvY7?mvZ?(pZ;K8jw$VgEP5zz3OkbZ`PV2#KEl&|H@v^%>^WF16`PLRecj zD<)wC2;vo`?ugGi)d_GlvIcKg5Q_92JXH@=A_Hy!vb(>8KtX_u;D9 zcn4S~%b6ZY3#b(1mkOg0d6;6!)fFw>C=^uY<_2|*PTl}CXL8fk; zm@}7l?x5bIn8HK~_~K&@PA0vn^ZkRQ(TUiD1mFAa#zu~{C>7U@|Mbl+T;#24aEG!tP?Yq|jfp(;Kti5Oc-KvND{^TDwq3}7WHdl&$7BIOl}!L1JQ-3<>y z1qU+#t;gD(SP(LoWw zCfWJ&_GK`93pNVYoxK4hZ`2n67+CLHW>-sGH`@9OjA_kDD=A9nqpt-%gd;X9KQb_w z4KtzYEkyx?B4FFiv)OgpJ-O6jtZdcP`*?m88fGU{ztGg{2JZCWBb0sEO~{F*UwO^l zm?9bw{nYlncWMeWcGWgA3SGrik=NAJlwZCF9_B+cNfFfZ#=^b;ww>~>lvI6f#c;I{ zV?kF%S8X0zEgssBYUtkK;W7Zgoz|_Qyn5QlPhB0-1}SPT4CeGfs7c_GIUrb)7sE_7%<-L8KrXljuF~9g zgI{p42DvzFK*Z$z6%&B;1xXUuBL4)iP1KNugxP|9q=TD=UJ|Z&{Q6=@zb(rVba1BA zf$&9Us=nt$sC+y`5oM8 z+G@&sAV9s#M%5R!J+YYVv0*bt31z&ytmmYP#k0eV1qzhhtlgeR`|Q z%||NA$~5eNDekl>>-)&Oi4flmRLC{REV$HwOc6+mDVX}}T#lqx4i>_kXjEV{mv15bfgfU{OSfJMlZdI! za6P%=w&S?d@!-3g5seH-e<#fF>*Y|QtZv=VFh#&GCE=LZX9uv%*OHrV?N`SCgA0mj z(1aF1;;U;PuR~I)3XQ+Wa-etef5mwh`C z@*aZvWhBSK&r9M7$?%K_B1D&S3C>U?eh&M0(Gcf3jc{0p?bXPVwe*&zVYZz;(wF;a z0WeQJ5)o?o7YV`|*%IcUcOci+|I+;()B3 zDK_HYV{;8U+HYuyu2!ybvnmu#Z6_kSpoXTlAA3bOy=`-)q0x6g%CiZPh^}5Fs|(YO zaLb!X8kV~!u_J(!n{se45g^LyTfALmHZ`?bxj{cR_9vD02l!g%I6+sk$dPU5czoi# z=Dvx!HMD`mMYLjN99uN{)e8$uJxIp_Oo5UpYfzSm-@wx6!koY6YOJ-Uh7 z#CUJfQ-C{#;laV=m4i-CsUgABmjl)#AjLqYaQX9Jko^DsMbza7^`&n5IAjlg-E7_W zh&A;RWA*q;g<4ANZ~GW? z8NvS>+^*d$W?i$}tfwoi z*uGPDx-YabZ^nA*l;LJaRlHwzOOzqsf7y&aWHdJ?p;-z*iSHGWBK2>c4w^S@!BdHN&WH|+nvSg^AH~-zv<9oh+ z^2kziM3g8{o-0KKiHS+vF|Le) zedH7Txpo0Lgy@hc?8ruvxz@7b^X(i*`@}8HI0#^GUS*;znKA(6EfO*v(V>zB@sEai_OA{>PTZ>YETM?>{yfxp3d` z#gCJ+?#>*C5!8#+QakTcFrDsRfdP*cMSX!766t8-+0IL(!WrqJ0(lwaf8iV70-t%l zoasl~ytMtYCj&MCl7Y0eSEMYm!xnf|U}xjj^I1nTK^ zC`pWfLdOS2otLdp*pkJ)3+s;qHz0VK+x=4+NFXXEp;^IV359sZhS*t{J3_rZxB7R9mPb5Voe)$z^VVbBiHv~7 z&Clp5XpK^^H%tsn5tq?M^yLO@%de)&#Vc*K-X}s(Zk~2<5F8Q#`acQ%gQdu1vT3&W z0gY@IJ7>G);-%k>znQmD$7QtvszLv-G|3I(EO%vrX`chH)7svN-|i!c_$0k|En6}f zZl!OR-Uy=n6*k833VN#FtMPTBPPzT~QNd#JJK`i378>leZ#e%?&}INffoa?TPpl78 zsOGI*$=8)Ey~X4XK(zrKcZnW0d>(uKd4=A4#VV{{dg(nOGx+eopnmCwtt1fMU&0#X zC!$s4_b#X|k?ax){|^FRqRRTy&MUeFVfd63TNQ=A-tkNXgcviHAR%PJm!9dT$Jk@9 z2i$^2!$Oh7jj-NX&Sfek=)$Q>zGk~~Mt*KxW61^d=Fktqm!f#|KQX&S2EZ{uekh+` z*O+#>jcz&^#Z$i|2%;i5>|rwjamNw=3lx{On*s47XrVt$f+3D`d5;TJ1U#_}jvZqx z7wawo{`yugIe$K`Z@z@XIYbdBa_4v#*f<~Uzx`;#w8)8rf+#F^e|6ZR=>)lXF}Dex zru4|}x8g()QS}wOuYFPpUp*A8IeB>*23H`x$z=(Mv!1qaO^XyQq)Y~DPM+%lYq+X& zK9_`Po1lW`2s9D-bO=#1b)lxq8%~qkQCHCS8u7n~I6(~|;y>icJ8CUO*&55aY_b2t zWG*;F&y3~Vq2C}KP9gtSU_G4YY>+Eo0%joN{{x)2t1lVk+)l1vD@39}$VPXiJ0I6y zMSID0MQEV#+Rr7{RcQ^p?<7Y5%DU>|x}| zv6;(nD^e7V&{^?Sb)kg~iktt)Nc!^peL#+QnjgR>!JH~zKn!J8N<~>Tsd36027bpk z6L}2H3X#=dcM&d#XNu2k3IdD3D4F?n6gRgT5#(z@l$T_Efb*<|j|e2Ht$ms94~I;V z6r7H-zq}!Q_AEUBx*~!=+2drrmRg4__pE8kpV$YAwB8~MLvbx<`IqD*o?*tZ@$y}f zI@(e*mN-Phz6L7c7E1oa_II1p!NmUDwRd+<1oz2!3r)NboLLPnrf{2Z#$(XdnX;ko47 zEo-+ob*DE%KYV?^{EGRJwy93lP#QLC+}C}w;p@L&4MuMLab=BK1#723IYV`XD7 zH(92uWTuRDV|`h{MCabyq@bjhz`0S??19m0?7SGj%u2<{i35ZMncJUjj2s?TVNQP@ zl!^1;zZ%!Ta?z2mjX{LL)fIHqq#tF3oEk^qL6`&4Su+HW6%H-V6GnM`M$$0x8M4i9SxvHc?3J9QyV=bz(< zdW=8x+z$>Z8?m^{yy6Xjcv}-g6xdk>>=2|ug;*wyN0-8h*2Fp`!rp>5Z$#XPf^F`e zVl`R!YFk8WcnULxKT_m=l`c zM(M-iWFF#9!+;)KH{yB?pz64vnhNrfKCSupQ)awqIlRAxTOxo5?1yJ= z2xPIrzsecvT|vN@(!U}1FB!0a>&AwX$NlJ8adkIKj6*q6dxZ^_Xy$E3qX-|s!)wkQ z=f=n9rSrvtOsD~v=VM+ZE=tx63HjBnbXx>3@;2%QEDkVVl9uJ|8%TJNrq%eo6BYO@ zwUUouKzRD$wIjW*M*x(hi~;XG=l{(D=Dh<(aD!ne%<3;XVjH{7{~XP(V^%fVfgD@u z**?k_q9ZpMBVtsF7yvn<=@CGD7tPHH(WZEeMu7Y*y&@1kmtIgqBIDv(A4y#)E|o2# zr?s@+llu3EL8bY1#TXy(kN+XgOJFuORQi*&;%DC&R9I-+&0vjr$P?fcdD`q7;kq5Ccv>u0?SV zC49$Z1gtt&YWozgCe0y|x;U z4G~tEiHg(>syhq-Zc)?O4Q$0P@XYxAT9qlld8b+Y1Q~&R^{;j+MavC8)87oVNaD4> zpIgzjpP!SRiCBLux2MbMOe%w!W$39<@*-mFF&8t$nXXR+L2X{u+c0!iXV5jewT@{5 z)annKK0IR7{IoSt6zK4RQjzP;?IO=oo*+3w6j>^*C(;j0u%{_nX|SUtpbU`LzDvrk zyB+@_;LR3)LrPPAb+oUgJe~Bn&}V5zH_BL+$MZ;kmCVXoK75O(P|EySYci{aoRtsQ zsb){VMg?@tfIXy*5Afj3aM@3)%^TIb-E{P(ZZo!@RBs8Q6N~8Iarjd!@-zuoYw`RI zP)xIc(q{1D{IC$)NMBndMC2Q%%u&Rwtk|&nm?U*!ghK8JLn8EJnt&J05zX`skH=rD zL4wFIhL1Kh!f~o>{hoD-*FlP~6n}o}4#zK|vZjD~u>HOBv66}vGK$`Vpk4_d&Uv{m z{w6aV@1V7KT|T|j!i$qaeY4j;>0)n3w$TD2eF;|W99jdSxwcGCpFYJ@te1^FDgFN4 zbGK~l)!2K#Qv!`WxCNe1H52?EDyDXF^7@#IB3k>QDleg-Vcq@RT_7L)i5#)K-E<2jkbfj;r z?#&T|8Npmnp>TgU{^G##;y_Q|)P4Rzg>g53w3-@G8b#F-;ulE>C5~F|8~ol~*`80@ z2dx&x&V|)G?R7POKR=SY2$DZ*NCKayWiof?0fY3RKP4%RQ)q=_gaUGMx>R|QJ-eiU z#rw1S*N&pMh|c)jlyY@n=6?P9HLP`RhRRkDe|LFjO*F-rsC-RvKCy!_Q^_DhjAIe98bJuyxW5=xx#Irhk&G_bIaZCRbk zYuTGt?KaqqVX8T|q!Fe<3<5d&c=b#`Sge`%F=OB}|NiCg1-9{~-Z$wKc?LwqOh&i| zADHpp_NUyErBEo<22hLc?XQ`a-IHlTe|CGHubNG5K>~6FwcWExljR)ql?QI|qUi|& z$;DX4=#`=(Di$g?o-?q3a{ZPpm7cVTQjtiH+{p5}e4t#`N9~ttyc1;(cbLf& z9>ofV8OESJk_kEdiTU)@c&!4OW*E5iBj>kl-4&C$$?7Pxq5cSM%L<(qrIyxwt*)Y) z)R%=|*0eJ`jfDj=ZtIV7HaGM;kffVXXjlpMWWYG z)Ty&=@WnqQSj5QC;Y_#X0BX0X?%wH4lp-k=D-C{-A-vaAXYw+h07jPkoNl&Qa<-VE zY;82~EthlSW%-0NJ_lA*(nw1{`REq4UcCr~C;6;rw-Kt1rhU0*owd-Nbb~BFu~J)&Pd?M8A))Z2w#EV1qdJ+YJ%W?# zVe=b2hPA?Zxst29TaW86UsTJbqIk0{yBX*Ax_2*653h&s$VB9&VBN|2CRn#$(jn-<6ciVn0CSp-ORwY$_7TdWKD5ve)4=5FsO&e6rik8R_{1)W!T(f*6>fevHE7R3hZk{U|Z*4ADQ4h|*8u$*d#Ic=i~d^jH=~Co)%+_zHq>|nR3$&e zuf&@R2T6yIum}r~IKSvrRMF@5-MGcQ#i*ett6=&AN(XRLC7ZLz>X!7t&OC0Ui9R&4 z$L>OxQMu!kDXrp%5p!Y$FP*lU9xr+&fHHZt@`+$9Ke@VrXAbTQhREgpJNg%i>}UJ1 zrSS^q#YuWIPYzYQz^9+ZTf{tM?}eFn8N;)mX;70Q z-|0DeTH;*Xd*NP+)GF9=!!Z#Vr}aKQKHhnx!00d>8WAhQBA}Hr@>T zuCMm2EGQKX&mR=EsMl-9r zIwoL0EG(=b<+#&Y!|v59a+dvwDPar#C;4vR;z;d5sRJ8!E6A0wuqksjQtB&AOKmAW zTvbxH_)UfMMx-f`kDIJ`QR3KZLO3}NM|#_JAV?ycU>AUFREnWNxtyB=V4~}3z-14h z)VcE^Dgr4&DDX z&G6rxMBQ}t0%*v@lqL>9@Xet!AuP_2E=^qMm7 zHO+ThvhOTB+#O!Z8UM`Dh1Wb$dpFdn?t&|Oce{5H{R?o4lpXtbE%}G{InGrWc30=~h#t5%9%WRu? z@!41%-T*1*h3c8@RyJ^cHdM%)Ix=70e4d@sP^9nZbxkP`e$T#^Kny#Y1O~f?G*0>K z4|lh1qoF{V7Eu!s`cQ(1qCf2l@jx|UeKZi$w3$-FSpNusYI9qe6sUQmbM{W2WI&^t zJL8X+05aD2OwOT3k19Qp<5DL4;3@7l+ z2wkgNE>EkdsF5_(@)}60AZoUH{Mp{ne?HbH+4&z>{o*+cv zW)PHrnvDKT3A{&h+PC^-*>1^h;+aao)hIr43(vfBH>}E?)KCyz{@kRH@=2a}S|>KK z;+9+;8WuM6&>ul#vb;8XFj@OksJ7%3VdR38#hrEl$~67}s*zkk3_qv`Fae!wtE+b3 z9b{s9z{MGNYRfNk0hGcBk{BxmwP-$CVyX{a@TfLcEMJ26oWfCFxj^3bC3ALv6eAFl z^2?G3O-UYfW9n={0$k#jKW^iOoJU^u2ysAz#nqmFTCaV4zD|3#?gq7dpU0ZZi2L_y zI2GIDx4s6D)kx(dI>gbCJO*D~G;Pw854>2d>o%3!T+bFV3BIF2TGs)vn85pRR}^21 zKA4p}tY(axs-CY7N-?b>sGr};^Mz`*{iGCR2on>NK4U>4hpNn^QM}StdH`0xD;uTe zB9f$`-_6nXXe>?1^Vm`B!?SbjM&&9-Pv6W7IhW%Zr$?NtyRzp2LF2mfLgz6EG9)T{ zD%J^ROb}{446!Hf2ydz6?QF@~& zDQz>}83niU%Muh3`jsu~V@T+Zy@`tjUroZMfu6CJXd(|66==K;3Dk(s|x=*h83Esh5m?oI#ZczH>HGgKc zootGnQ1!q~ycIea=R)PHUuGq`Wceo2y*)MpWesYfPA2*Z{;l8MEGyk4QhV`J|K8E@ z>%to*JhbhHcKC%xc;0jp*Vs$#f0ry2dhh3D4-F58pXkcPXBp-_DLAPzJ73W!;cD_| zuIFQH$nu>Z3wNbaWM?J@IhaC7zgR4|Y0@KTxX%)A`6{qC9YhDW><(lT@@%d|Vn6 zGR8{G_}wyk^Y}99{qx@0#-f%m1zserJFi89Go+`NlbahT+rXti(c3#d>hx=6;#cxW z8mOT>cd|_LaVM*0m=rV&MN7|xH0m0Vw~A0iavZ~z?!YzcFz#sZx_bbv+GMf z&v&FE_M#_!b`}(4EHsbKb20!F@7%f5=OoG8wYb}7Q5@%FQr^8=&BtriDT-KiYt%6_ zGt)yL5E;)H@HzZHYsX_&{}V%mdhbN07<(?GW4qrltB_ZFH=K-BVnRP*^zWc`=liDT zc|H6o`Iy3zUFO0hOi#GOg}t4+%0%LwEs186Vjxq%t2`c`3-}4rL1De8z50V zLpB0VI5m;QG6bfz>nss*d{<1H_TCOP^Q=ar=j9#7H2BckYPp%(eCXA8JN#zHY7SbG7+hqh=+faRr*uhFCCkjWKd>JV{ zyR}p)SW+PX^=RLAF&HpeHM5oDrC#%?#e&|dx6@c${W_+tC3vNX<7{whjsZBGaYtQc z_$?qFdrFu2odH<>8?8jpWJV4LAy@lpA;RI$kT_@m;d3fLNgQBqc-^1!#VzVD>M%;^ z_!t9x=U~jyu@3U$gYnm`EY?uF@A2}JPip9|)0z|anuiOFz>7;(i=Hl~VE_|J{|q5b zc+fBZJ2B|95!L6Rb;%l77Ca(jv;~$;s$AxUcgjnP0b5#s`2&V?;A^mJeOiz?cblrzj_o!8Fq6}NZhMZwU<65~(KQ~2WtxqE z!7Cc5-gbN@OPtn@f!YwnvV!8L8#dxiZzdz4crg1P` zyLr91cVNJ|k>5wP&DK1aYce4M4<*kzhJ7JPf@&mEBYF*-69TtWEFn{*(`_HB6GdqN ze^CO4D3{54!>mmwvB&LMVWs8lj(se?Qc}`=1%P&I>J{x-ZLl8jK0Yh#M<*?L z&^pA3$x``$IF@sswY~RBiDPS|=)?20@ViB8KNe`h#~J-0y<7-)1gSz>O=_Yd%k-b9 z{WRS5P(cCt7p70HD-I?7T%8FNz!~lN*c2(~<#Vy&{ykzE$9plY@fG{TdG*Q3l*6T? z(HY1d4JE2?y{jrV5P)dyY?f`{8C3)Kg}Y7s!pryAH(tuRA}HM};_NYiq1tl1wnfvSS$_8a3B8RGXt=Ohn=z~hb-uib>Hae}%PeUMmA z>0N`-Lux;|Dk`=|9VO$se9^f-9K{62HA;w6nMcEeDB)>Z&1Fed!j9d>%8k$dlH7K~ z#Z?YJIK_#_DDYAwl&!(#QV5-V?O@KFHtE+GfcwCaRAsqb&`QfUpJ=R}0xQQEBVa-N z3xl6|xV-Io0`)bfX$y$>-GO&pVC1J`Pr1C+NYm+9#ZwoQ-Ndm8WL4i3 z3ZL;jOc~%eDw{6mPVt|U*Ht9+5dD1Lnu}v)4P^>qG{0R>Kg>J{d zu@SLT3f^6rT6FC(mXI+PRSKg8^Z#>ur$DslPiZQifFub}Jl0f3G+Hhb_~gpAxwvc8 z|2jXMV#8*GC)uNy?1>2>Q;f3;MTHS432?;b&PgsmgCUaso+m`XdinK%2xlgS3#CeV zheu}8Ve2xk=JW6Ait>4wPe)H+EAa#-L~G;UZk&#dQIWotE(UViL4F_TOs~ys6b`|p zWf_i}*xd*$-b}4wy&=4ffz)Syi~i5GU$H*eq$!-Ov~6!_H+0M@mhAChx3|$kUdwvc ziLYDUjO>z*yyko5va?jV!5BDW7_+RL(PyEjr}vPk*kP_EjAGJrx2uZlS?Uu727YrV z?IqzeuHU^9wcBA^V0$!wlf5ZwQmWac(-vjt{C$2d?(PwXUik}8W z@foC^AKiQ7uAy!+z>bERQlT*mPiZ0JQn?nbNMsP`t*Q~{)I0hb$?hA(Wv1^|{CNECee>gBEf|(3ZhA2k3`Y$?rga&o#o?%czX)D0imr}1W0!|$r2 zQ-F$n^&UNk8*zg@peU}nRcitVLU(?P8%>K@O|Ptcx2+<#^NB6Q(wxDE3;%PJjI=oDTif+&(py$_A%k`(6-y-BiLu(L3?{!Pgec2v2cMqCqP*xhg#SuvEa9>p)nk5!(hEV|gT7}M3&tbJO(?Rb zK-+NNXhwoJR`}YJ*|=aBB{y>vUesGEVwEDB2I|iEdl#cw=2SR+Hq6-qhJgh}5~q>6 zp)}x>{B1g@|BLtq7;JPb;uJkXYZn(3-0|p^S{#fOGSyZqV6OBv58fsPo0QDm&EIdq zyyq5R=- z_-fUU?aX`)Y6~Pl{krc;%=E|2G@797Sp$Xl7VnW>GbbN`*H*y_(Q;LKJ6DuhsZuYk zC+C;RUD?d9+6HB7Z<}Yg8<5{3IGI8%f41xKL=(GNb!3^}Dw0gAV_XJ<120c)#IwVS zjJvm|C48bq5&TP)$sQ}Y*#{k~ufJB7?N=vBd#I%1;IaLaUf(EYzU=#Vb87th_LY3RX<`o9o?U__h87H-gaDv{ ze$myAMd9nJpBj?;M9A(09}8XV2+e4MCj(?ni-hBq$kj>;uO+3ruSDS5q3fEV!_r}i zY;>sf#_qtbv47LE?`7SJ;9aN%I@apR7N5oOCBL!6Dw`vrBR#{?Y|Hsva%2KCN`GzG zFT_R>53Y*`zX6{V{_x$(a2YD=px0yT&a75WRtr;N)w#Of6fv3Z-&o}{*YeQ~T5&Zv zzK0l~)Wv?^*w{$28^N3(W6w_y|I2u6eR{CIaqC@JN1>*Bs-hq(7~wJFWbgwclQmQ5 zY21-uW!R_1lZi-s^i;|wc9C$ckjUp5&@xhoMJ76TOSP1am>TI|(UX&tm>%zgZ}JA^ zuS^I>H#a4BrZ}>E7@x7h(Pv@-P)B-o{TUup3LL_s)J{%YphL$rJU~oBZAtRtezY2zyl3~b-Eh7L)B$|g zm;L}*Y|ts&LQ<1MYRRpATOg?8)04-(4?~ljB#qyilv{32)(A<5e|w?q%Bs7XAB0fwCNR9kMev$$uupSuLyh397-GfgkR6^ z9;}y7CEwp4)agmS@8QypG&zM1S63VoLUrFV_Os%tsbBJgEVQ-Zr3nhh;!sml6ye`Q zH8?z+fwm%mO5*;{ONhJcpD*7$Yl>ujYGe)7C!aM1)}>}xvYnisLQn~J-YKrGW2wF_ ztVzZhFA2hW^PrC#jy)%rmY4ey5)x_-4i1d1truB2`~?GR#-j6l8{kw3wOoEQDeyE+ zODjNe=Evl+FDlKSG8wb_>J~LspN%f?vBAj{=}#ODHBD)V1Bf99gSx<{G$G0!#RlVb z$kpL+?qs+0;I;wEdw)xP=PwcQGbl6}c*JlXiPC55Q+KVlp5aI^!g%uctRO z(%;{ow|bHVy}J%%jdzwoCM{6doDR^IIZjRP_gtLye7UR!jL1T5ue#G;Dsm+Re!J&k z->0TNa$)BRa#EH)BWVNyR!hhxbbFsCGl++@pOtkTYVxY`M#!9z1;W9Q=XV2~ zyDNxHk_d}D4qeu!rUDNR%KVZ~sc=&z-VKaFA8NP&0uiXSJJD)3j*hN(I@EA;3JVGl zfr@Dy_tX4*=;IgNE2H|IOh)!(djz7@{`2stidDUJSs>VEXJ_4&F%>Q`cp1N78@~{r zwfw!bbpNtL$aLcdnaPM%1qe>fe3einQW@FzrQ}?6H@(_+$FVYp&5Q`SKTzp>Sv`G4 z-HLLV&NUxTpr=9x zBv_3%Kt5FTuadcb=jrz=YWGMIdyFMGLE)wzlozWPUObD7o7?^IwW81R?ebd{`YL7RtbOYPvtvZ^j8trNzU)(r@&@onv z-7ma2n7TNha_vr%p+_Q-P~@cWyXi&PXsHEztCXh2%NntWjyfkKXI=sqzF435eU$m~ zRd3$OG&zMFARZbTvKQ3bV?(jQg3m8)?Nr zkQpTfwL=}=%MWvzk056%$*Dv51WY~oAXm)DDkBeZqt3EY7$H;T)og!xLydO{tR!y| zhRPBjRd4n7-^F!a5NyVtdlWmYzIcAumLU*k!X|CtkEmA`eT-{9FDi_F|5c~qb>dqi zqlDkX!%r|Mz|XlqV7jpO6RM6W$ZaUkbZ9ReD#Le%3Rc>@hT1BPJ>ECLZ~Q^h9RB@C zlcAB35y%{-9BSudj9AYgrvZ1iQm}j3Z=L$~0`V)`yih|>YmA5S}`o=wf~ z+Gn0)$ye-hqTV||q`QYkQ#Q@&+i#@;hk~~zu`yP^q3%JH>a86lh(v0LCzy;)P072T zvV2XO(hq+{2=pL1&_TLineJJ4DcP+Gh>Dl7f64KEu>=?X`F=5Jyx3%Z@wPvlhgRVh z^#eXVzpRBP-@kW4iu2YhDlaG0R$~Z!yzRjtJ;z7Yca55R$F^ivXXT^&f^S#7`9Q4r z+EfAinI3LViil+knBN0pcMEHwib78g2BYx<6RMqi3mtWnHS;MWwp|ZCAd0p!48*LO zIy!Eqqd#>jPezTw*7I(VV=b5oC1+z-J)L5|p{SfeVy6~G<&I;x$(FevO zFU6`E358hh#cs_DLX<0jdbKoK3gsQ^ze$>eXC6{~a>9eu^K(sV7ZSrh zQ(J5+(|=KVu2xf#v{M}QwvxiZ!}Zw(RvbEq!*cFbL#YUd1#{2F)wyw~4+zLF#=?vb zH_fo%nyG0^@RHkyCp1OUodKq#B#by%sD?&KRvS@hT=Aw`Pu~QoA#gqP`CUd$$Yrxz zhvW;!oAqA3Apm%-cxj1qv$C>63!#qn-*Tu&g4l#w4`qZLe<_jvKI{g^$h+PLPv{hy z3W&VxM+@uI!ix}k(ICzI2%LF#bHOcK0h|Ze@TLy&XL=;nfjvG&bMaBG{aCSxhlUQM5oI%L zdk|&)k&!_@-JddkPO@xHQi?-4v#e~m+595+W`H3w7$wPwOT^ch9|!NTmS$kx`pd>alSAp`nY;fNDL`0omWGM2wrRj^^sE<8e6gPw9@2kTUi4rS4 z={P@8vbz7(=OKu0?=zeY54PC@ai?c+2Dc~;YI~zbe8k@WOecUh&%M5x(i72AWh4dT z>PS^c6#kWs03^%R5S;HTnAg%&SqH(Lvio;Ej_2$It& z-wu3oi+kVrLl7|vvzUgdyiP(dsGz4uMjX(X`6op?7v;WtU2)*MA0Z07JT!nuhEk~- zC95F%lEq8GEcwyo+l#K`Z{5;%S&QyZ-3z8^G<+0viZH8~XABVFzqTKnoSK}heYe=1 zbPTogf|F!iHL_m~RliZM8PV3mgZo&nj!0E6dui)eP|yMQdz3_(lnLcL4sF|; z{g3k#$LZzgDUo*oR&b@pA(ibjW|h%oenAIG$^B2DLS4{iGBmNpXOUK+%@*b+R z8kv|(I6`f0b*^0t2ZsV-QoqeiQ9Z@!z57ITCJzV{KS%ZY6L5Tg82=L1)aw@~H@as; z1>kFfobexEy$^(u0jrfsP;TSbmT?a%%>B38btlfFyHp?#qzzFnIrgj-idI9`r{qgR zmAkCHfJm95FzhG5CZ=9e2(!#tJ&k<(aFiX8r9q#$McG`nPpT z7sjm4`zu(W^hlItokUKTNe!0uOmP5dgHxoAoAs>zZrDS;yE;UCsI3v&GQ}rb8&bl7 zcHHEw_5Uf0K7+tu1^+g{$xNOHF>J-6zfVU?@|6%~ug4?wi_08EKB@kN5-GWat``!H zlg1WDH{;Kuv=gR#tVfri$YDS_qspKN3o)QYfvu)!OAiHdR zt;WK_5)==_2Xk2i<2b2g@Qk-6%5x&RdipnM$ulaYeHL11)zJN!V}))41STVtnp{*M z8xe}Q!DHkRgR#ZO;1-{waa`_$$^G0BjVizZN=fzD+nu*<0cA6@6v=B5w_(5R#f>V` z331u`28mENW+XzA)24fHpH2<>$Fy)MH*)wZafyl?V+RpBDhLyn#*m}>x57T+9L>_| z7-Um9rFEh*$#-;_f`kkssp-lgrV-VljH}iJ%PN(k^+dBcqoZd zA@Wg15-ZBsC}f)Pp-+xVXu?igduHSf$fvmg{YJCTyWgi5h443ZB5;nRP^AN60J;22 z%Tno|Z;gF?Z7QotS3U#!nl%xQ=2#$qu>&E>K|L)1 z$Ul`XJg)v0+xein40hulSiiZ0nuE>~pBae-XbU6Fu^*mRdoNS}eJ4YIVLK3>65NBG zWdzD|G^c)e^j{q~eJ+H85USJ|-<%xvCDJqH9c&G@C5pO$ZIPP2NZ;m`+uaR?jf3-2 z*~5cfCjNvJfQgaQFYRHu){DwKwj(bYEqYAreBMf*_HMg77=baoNI&ZAaeR_evAiuZ zMX2%Wk#gj3Bgcy%pG|(g7uJBJ%qW)~(OS@y>(XtYj^He7z1>#(;_${rCk@Ib-)|s$ zvyP$O(ad@I_psRq#?i=zUqR1p>pSs^`X@roU z2D8E8`wd;NYUU!25(bjRGE*Ko_o>yZFLj}hScuWJA2A6L#!T29x(yx&@sE#imn)A^ z+GggLe`$a-9{9f~JIjEmqORW$-3%Zl9fCAScOwYWA|NeDNJ{r1hEA1kP(VOw=|%+U zZXCM1bLKrh&;4-kxA%U9GY97Ev-e(mt^e=8ewoO$G_;jCeTaCE9xaNnhIczEdP2}4bC~CKj<3!9Mvnf^ z(^bSx%9Ralg}>rdes=%jn)cLn@1d8HSw3#e52UvbMjD zQU&n^ZJPzP73XNf8xHQP<|+QmKgNgY05N}MJi8WGpMHC^12s6jvT;K3Mb6?B{uM5= zNC7pI;2kaTHI9&*J&?edJ|XgIya(-0=4@&$EOV4dXB1rM0;F6Ae%rD3->?5j2)zwB zqNYG=pwBD7b)&*I(Ok)wse%CgBe=#9IzGjyC)zBgC{|rpXYZ7k^!dbpDnH<>ugDB4 zYmNeOmy2D*U!%}gVC1xspb}Gxa$jGiF6Tp_38>zXji^fp|Ia-I`|;^Q{y2^me*%H0_S435oCgG)(gGWRtWr9aakRY-Cu;1FY`1tp*QqZo4TaTFMx z?{BGFOx{wE5@YU43&x$dLz zF2rm@?i*=H0+dT0TR*9S*4rKe2=+ww+h2>+4is3pnF_w2is-UVez(i0{wPtW^X!#b zn-+&y{GuU;ScM|f^oXXJ*x3l^Ji<>VwwC69G61DLuhB%B`Fjef#t!UOpbIj@HONE36zXf0mH_>sY#HQd_N))u(&x7CkguSwcv!L^SIOJ>I7&T%2I=R=lq7||7| zVs1|gHQUf1ISWVcs&bvlo(azh^jui%rGwvJW@O9`U3f&@P_)1QXl;1=F_4?g-x1v< ze$5+jUV{I1zPi{j8{AZt5w)MnLSkq^_$<_(|Kv3D_)yaPAf-`vp?&UT zU94P3`xUy3qX9NoOxkZc-5I(a_W3Im?^ggyBI+ngt=Sm|GF17d`{hmOAo1|b;{>T* zFFJ7bl|%vAiS4F%P)ELqu61$X4BV-Msn$MfBO{}c=$^M9Z3V@jJV~i{Jx0?a^wf)A z%i0hfHq6<2_~N*5=i0b9f^rW=N4!bhrefD|dXSdAVf%~RMdUpQFTXuYr5JPuL@l4& zUwnY4+U?ppl~!kDmJXx1Xe_j~0Xw_H2+4G8!2K|*DFCt<<%0TTlc$v`=k`u#B>1cu zd1_UA3g=>mg_mMNP^r*iqj_@OhdCz4`)_sTdy*lqQLmHeqUv$fn@5HU+tJMT45R=l z>;Ppu%(g$17guvRUX7^BjdXyb%PABZ_;yww!X|b&7!vAb*U`)ro+IpW@VD*LnH`S% zDK`v+Ex!cYZ;mJY4Va{MzVGiPfC%MY|9a}wcs{O%Y%45$XDvvj#6?bx9hgxB>aVdG zG26gr0^t&wQe|Ih;&E7b&XXGIxBy~rSJpLink{Er2}d-4;vMe$fnLpTIHKfuLnc+< zFP;{2Ihsys<-&@hw53K7foM{#VvX&sNFXJ5-dEzjXhlJMnss^Y0L|d%_IbUi6joc( z(fdp>Z~RqI>Lcf-i}ooBohb!_5d%M;`H6hw_OoAcPjp_>CY61usleksLf{G4S15ax z+w&zUtwR06_LU(Hfav_0ZQEf08a&}EssXZWN_nYQV({1=%)3&|e8%IvySEFEY6`>S zyZbKi?5gE#w9=OGle&6jk&c#Xexk+~u##5WUX9T_Q{MCYDIzk!sIJ3G+@iJdqqx0M-4n*PnIdu~9%@l9#O7Y@}dD*GwY* ztjXEfV-u;*MJ{sz)%?CEF^6R_$Igwc+n=1i`dL?Wp7_rE$pce@m>nJpW6*p?TFOhs zzil?oM?=7z!wIcgsvy##mcFd==(wk+XkgfM_2Oy?j_i+7Lt!9^W12GvQ?W$1mJfAz zboad*v#XcmL}?-&O$x$6v*3nRMi%tHWVF*`CM)Y@DK-fbQT!WpnWNECxu)sud-u7I zjDJQpvP?+eJiw0P$oqyKY6ZRWCvR&96&*)Q^Z?Dz2PBq&r2b6p(c=!i<0pd**FBk3 zRm;@_m8-w0M_b;Ckq{76zI}%6xNUxIWr;?$Ino_+HXN2c@}>9(f!~aCM|f{;M+{UN zb{KHSSUB#7S11xDcu?fk^VusvCKEx?mJK4FNjO2&?WZR$Odr$ksz5zz%s*Xd9GE=> zz_-N1R9mSeSnK`HnM z8e|yJ`7U?J!3;>Xp>Q_=Rcdd-wimH+-=JixC?p#Trp2XE8-?^l>AI+%y4NaNGg|-3 z#~}bEM|d_;($P5SLLplH zAdLhg#+4Ho3T9w4p>QfeZ`M*|Pep?W4ra%^(tWg<>%%H6i9ny0zNGZMtndCjzRNvt z=A$p^qozOBwoB2gMeqbPamuJf`8OGOAWu?wOneb{AeDTS<-1$rMomSfrK^iJP|Z*X zE3%tybbFc;cx$(RwEui4D=boIsCSi&LSEn{5=D?8sxtT&6I5viZCND3TH?~eZA)6x z53Wf(6$Dm|u)ui*p8vt^`^S$TY%k^#hpg$FEwz{60T;+Cw$&0XD; zx>r2~(`oeH>W{va$K!HZwW!&yPAcJ1@%pTmP-x8e&FdlIb0b!l4&oFLlAqeYtc@zW zmE4;RYkzMpd&JGGecwHM_OuD2XDx(31bb?tvLT1LW`ZFo_!g7A@U{FP30ot^IVsd! z8Ts5{2Z1*YcvQ$)T49z;tce@9oxfkaDn@o^WCPzri8Q%y-KS_P{Ogc=PtVc<`|*)A zg#NG4O;Emj)41_AQV!W<#qWx_S){SP=|A&HY{6SMyuI&&!6MF%WmvGrey2r7^Z_O z0AysY;1KgTEZxG7vWZO)t*ti+@xL`}_&49xSigSQoh;-Y)7qZ>-8owqdYBVv<>s^Q zilI`NI6wx0R2iUW5JmPdMfMha`%x0|F1^>iz3N+-Sk3P6Lfe-!UJ4VJ--gG<^pAyp z%$SnPtTh)`3?0ISu^>7E%zV@=(M&OoRe-L`*?xNu#)UqE-K$P*LK-{fgG&VtXb>(! zQ!c4Fh69L%LGo}2J_tk!Wb$;D{*D>TS%~|ImDBnAaBJ*SS`5_m0(#vkpniQZpNk7I zGrCXTZ3J#+5zzR{7x#t&4m=e{*K`@Nc{pz#N|Hq>x}9YckdLR=w}V`|nHD zXj5kzas#SBMuQH~p`b!&(H%ey3mO;1R)`1+!VQ0|%FZZ-v2z_T6Wd-hkRv{)HzUCg4mLO)Y%?0G}k!Kr|b*UMPAtw8KTq8rg65Hj3+>zdVba zXzDn7a_QxsUsgu3^YXB=e!%*Hb^6q?&H>z_DR*~E#}*B+Ok_?&IDwQx%i;Yd770&J zDIqV7C5$g*s9T7OOs2UwUWY$*N4Dbx!Mly*L>|QBtKI`4SIZfXonZtZ8IV1I^@z9ACd^zwKJQCn%I30HT9_Luvp};x5xaCw=*zB1M_t2 z2n;zoYhKzm5sF;PGMhM8rUopa&;u)mHWp_YLfZ$TkcH1FA$JQ`PfB?nu3jSPZ^#uu zo>dxxxl+*t7W_^ZoZBC$!Gd5^ikO>L>Pz_<57HQ=MUV~dd&4f6b44YKO&Tp18S{p( zi&YXsv>dB}jub+R%E*%VlXl$%`o>2?b|8q)!#f_9eZpy%e><0^Ekk_(@XEx|-!Ee| zY-ZReg26zhN{2}!Nh63W3{W#k9mudN#+Q*aI0ZBzVv}p=q~BcYs#?Gi8vFATgfkac zBlvpx)|+KoORnUrKh+pu@!m@$G7wM45FNVerOeUhBhBr(vnS)}fnNp0_Ww@A&k1CX zjvE8NI$1JU`M`mS<_3(Q_x>v(;na|I&GVii=Y?yXx&YWwwLUy>)hH^KafhNk6es^RZcHCc+5w(W_MyWEl#2k4xuf zESG|XW+%^>$c2CW5`mw?uR9Wun5w=!co$q_Xl$L=>iWl?_)f1=M09MVV(j8=D=n~3m#)k3OHSaMdgCHajWAvw^Xc+3g zJh6uKk#iVR%iFOE+!R&02^XC44}6wmOq3~M!%}`L-s63R8{m*J6i(6ix}5^`^adm)I!NvhDP%qi`PctFh346sN=wn8J8VmKFh?9b_ z?cX1{ei&~wZ#X9fxl#B5`I6Ca;~CyWO)pF2*&TxvG~a-`;E(tdogcPue4f?D$i(Md zs@pCcE4UwC)7Bl##>As7iF)k#!{n6@okeXt56Fz_X|HEZyiD&3c>{0q*XW*&xz63R z?<}1!G64{kp>f8SPyrIW6U0WY0*7%#z>Sm^~*v?Z!+WkL_i$__3`H+WS;(!_VHdZcDx96;6P-7VrW!|RNdbiW$SEA-tD zj20#Nhz{Z{a(Y)DpV+^?Rxj%4tz}4h^XExv29TL2MrfYOkVT|ef^I-ggf2TGxMEmD z|2rA=YlzK4AOv6DLJZQxB7-j8NVDjVVw%5<)d7w)CMH>@s~(>o9MWu{Xl6sMV_tn?OI!HthQ(L3A4~8I+%IyVsX$jJyh0L(8z}hz!dsEU5Hz zO{|O2+SB>^9Xs%D>!N{`=D8jl?ADfaPAO*eGBvgR>V1XVkn{PiV{g+JyiJk&iT-y2 zDay8F!!M4R2NN?`&0k!WHdd51#pS;4UH zfl$3?>+!4*L~E*40g5yEJoBW!_+E-jDz;n)>j|kOi-jHI`a36E2rNWv=!nxtrSbaM^Yzx*y_z* zJ)o%wMkRGeWYxqQ$*)D7 z6CT)wkR9mpC^z1yM>~{3ix{E?xTvv+HcDoNv^VxJwdmkfzY3|P{l;+b6OU)Npz>P( zOX4tCEX;3TpB&LpJj6Pt`j3(5BR}ZZY~pLQJUW%K^^MQ z{g%>=yzAiPuF+6Pd;N@MwzZL&C;I(ks_2y9w_{3e%QTy>2}jL>$bp~cdcDgJ+9d8fyWsA5 z@pgh!0>#$A8`1mB?T~+V$ENZ^Gr@AC$fGhQP-&Ep`zuujahYmov|_#;mGQ!J#!R`o z3hEnonM;Q^5mK4c`9R%;_Ml^BoYl(*xhe+_J%GPDSP9}Fc)bYtRAgQF8u+5qhCKwD$qg z+OawE<*D>VO9O8!ZzJ-DIud1Z$OT7a4WP_xUl~`f%fbOR0MXI%S{2qpinKA4Cs;FXj&=#!B~^1H@yu(U+UjSEvG zHS{wtK2U1FkU6Nrh)8ap@;NJ{}MN#CCN08x$i)kY` zs7U%*I{!w|oi<7lwf(w>ca;6TMVYuQt(}27J2uK!2?3WoJY~?LZ8R|f_OT|L8NEZc zGdP94)3!WBn^w856ncMPP)5y->Hi#hkX|wNN>fW(hb4iow z{rt&hC2mf^&t`Q$#Ty$LpYhuoR-l%b{$d~AhT&)=T+r+YZCXG;1;|^2dbXBAwgDmd z?|MI@cl5ftqLlr)g|k3NF7+S0`KwjkEAqR`h}cTm?=NI=&9&b@-h7gp zS3ikC&12jE5j56vdz|s*hf8uyaT6j)YB;`ood-kRHt{{**W^1S4tt`fK;+JcUxSpU zQ~ntE7J1C@aGM2v1-XLtxo>eomiE91=C2acfidmOL0Y(4`QXutZ^jQ>37xcEucI& z8aht zg}9lyJ@Ry(k2Kjc>-wuN%&>IEofWvT;Ic_@wS0s1H;Nz=s9TFoRwG<^%16V$B7R!; zZCS z=xHR?v!oVgRL^r~d5%{R)UW@BAg|W-83iBgKaxwb6-vGr<-n>*ED9h?E!#w)!LFbF zE~hLVk&!yGi9!kFO4nl!Yz`^ZuInR{9MQ`0(5GY=S(5e$x#G4Pczk0#hpKn4m6MW? z_>9-(U>v=sfu@DAT>Eby*2gtb{@z3tu9K*KC{T+@~uR|yMaAyk)E0U6J8?tBFM z9Gi!}f;6g3#wXA)q4DI84FQdKY1YS;&TXRm&M6WHfH^i%y8TF;dd6TKF2VIHJaB-8 z!(ZA^weDROkk)DOdyqyGwrmPiwwA#zFFm(=n5cH&6Ia-$ftlTfc&&#=@{yWD*}7hR zdeTWc2JLnd#`-IhYBC9F2vpCC0C$G_A;Un-;fDM7?gze9ycG!IONRs48l_7sDQ*~_ zJ999Q5$@w+0#XF%I)z$&XbYx+7`#%a^pQO@S#C>vMDaZz55SOD77a_cut(qLlgrj zJ{*0~{$)u9SN;O}kbssek-cvtdqa@%J&CcsA61_m-+9Stk)#`| zbifqJqUSW1m6r!&O&N7#yr6?_#6p(5HajUT)G2_Z5$*B%)fHnd4?}Y^wG)3x!B)P3 z>+&n!ju_syNKifiOZt{Q7NW&=p5J}2Xqn(FZ8<%dfk$|Cba&~+lsRPC3HZ<}IhImO zIZ{`$V*_WJ5_m&yHs%MrNZEzDfWD1_$lnEN&$eEzR|gtY$y>ZCq{2Mp&D2h-x5aoV z5bG`;%grm95I{}evy*BTs=^fIUejea6~u76-gAIYTcbMWJtLJ z(b~?^Y`NqEF=u%=p+W^%OBDzr({UQcm8OT8zP~ll_WCUwHgI8l?=pm3NodaLz`H}j z;wD*Y_k~HCCue|`NOt~HDYK#pQ9DLK}AKatJY3pQH&G4wDwxV0@|?3 zx9}H{rJHzK6z}DVCb2NWE*DMr|2QZsJMj)@dVMrAnmkV!u-paEunjUimBsGUF`HF4@F05dn*vhsBW zAbbT`zkxKJ#bqRpVbrhAM>$pv#Hd`n#~Z;D21r|8n^I8A>gT_D$X&Q>*NAhe!~+BR zKe$0Lf3JUwm;&GIsN_FlyE86}5(+!a1`+B(7d%(qU^?hCw%23T9dy;1kor}#9qxr1 zQAA`J;u+ys)zivWwbJ*v)72dmlyJmy>JJ8$*k7;mB0^F!*m#V`BX1Mq-|A!D&|+!r z56RU{Lu%}`_xtm_^MGy3bBg8P%%Ck=p^5sltJ= zjsB+d=1_@*)y3f16VC%X*2`m;e)RErvMfUi*lN4 zniL@I=?r(f_AemyJeUn_j3Mvfb62#)aX(my;Iv7$Qa zWtH}tfJ6&3jDCQBlU!|hL)nkQ-I#_P6Y1nR%1aKq!S5~pKbWSeEE%h zHXf_@!-`(7_WPsIwFZSc9Zk#}R4b;~t{ghiMkbB)k6lW|f)*M9G|2Nhx093@3MO*? z%J)tLpNR45TYVo(KNJa!eTrWG#1aRj*}p%Ah!(}`I3x0U+4c`%6a<~x$MgcvD2(cz zl)yro$&--VxfS+P} zBo2X_C{{Jvq%j|A2Q$JZhD~v1Jj@qD2QF^aeHD1O3*X}8SB8<<@F;U>$M^%%(K#B> z<{9bOcNC_WklEW+x4x^2Zt%V!^j+)aPJ4+_s`~ugz3KY$OKW0dfP@n&M2d+4N3Cy#>E;Yk%3`-w)?{Nku%B2!v`gTPR0+FBPn(|?guSn1`$>xTNKK3Sy{x4=8e;NBFb96I z*s&(~)Y{y_RqPhGwNL!9JNbN-Of%L}51PTWtFH^^hk>!nF^H)>wr%(^XHZJHLMlm9 z5}zbAe9yUQPtMEOmWBFF75Yl!Xozg_SJ>%S`pFP=!aLI@p7C`2zdk@u^7S!+i1|tE z<4U!l>>g*Xf(YcxB175}NH1qCiwkOr$i zp9D6CGHr0x(IlbyTG*Mwj`9(i$K7U6(4X3Tnaq`7%kmMzNxF^cYp=yCmBvw?aoO4% z?l_pKPz>NlA2`-u_!bYm@jk=ABO+im7j`G8*I(hcWimzXZsz zw_I419T(~%mOev(9UAiR1#}PE5=+%eXu%zVdQW69dD{0SC`TSDxkIohO;++8op^un zASj*hICBV^w@!+Mc-Y^J8Oz)Y&5u~|<`Iv%8%sXw@Hu-(_lFh1-D^J!S#66v4kUsx z!jO8ZX*zQHK|IND=%`1&SbY1OFl_Hex6eC}?Q@O<(K+ySYXpOhQ+UP`!akNZRN%WO z+~RR4*>V)ksl`FQfn}|SYXLiPh*#-~76KjjEp-)w91yzq9<4dwAs4b>-VG-1nFH<9krTwAV zbKGP015nW82vJ#-FWK%Ik{G3-#uA?}c-B4!pi*h=?q9Tv;P-jsS2ufY*GP`yS!&=d z<~i%}Ovc8?6LJ|=qq7DX>rPbDBd>eeApvCV9)+Q$y&E z&%c2SJ2yS|+G2cXyL|b&FJ#Miwj~e`zgrfNBvyDrB_~P~VzG^_EYC*fcz$utoH``O z9;U0$0~*+%J)&tY4_?|c>!?E^~ALWiv+^m8|0C=OB@^Tw&S+MksEwtprfG~0jMdyrt6u!y27@&Sl$ zMAfe|6*+c}w_k(jAUK4#M3}zI8<^IRC{;u{jT}|5=Fq$ER$i8syDbQqL zuJGpxm~9MmXBn9Y3br;TZ$I^jx&_j{DPYa$VzpLOAN(F)&{%?*nj=Ink}UxZf>Su>HF{}E zNOHQnkX2fJnM@6}dE-JuVaOc@9#IsTh+jP=`Szm>)VGVe&9-HGHbmv#-ST7iW@_s_ z3i(8m?dJ(TD=u*iKM_enV1Z6tNDX`mN(^vAvSQl)2JSoC_qMg(eH^l?vaz8itOeuL zKZLQT?z9wRv!k;5Tp8PQcO<2|nag5?zLy7bdg|CK-U7aN{1E{kNs};v^fm~4(IDU21fxXZ_Tt3n%>BJsmSL#+j1+ul(jbHi(}bU{5k zhB{sfedq~X)Vji4)VgCGtli98-q5O!27k-fhWOQvf3vh_(@vPrM6hz#B|Gf~~n!CJW) zY7c*E(a;%bz5s+DOR^b`{gN2n-;-}r09d7lp zaPwU61A+bv24iF!Ba7lO*#>dD!n7tPjVAZn0wE~J^TTjCS?wWaXEB}$BSHmTD7JYY zyUSn|v@RR6M`mMyV6yGKW zD3k@g(Uc*Ik`?E1jm)dBr}(IX4muInmE!IU50gOx^-nls)~ZGs>G`w&sc(HVSXbMKau-jnUmU#fjug?-w1-??KrlTTX|)u_b=qN)s;e+cdeJ%ngx8&T9_ z%4Olfz{B?Yg}BX|7;TBQmsU*(?`ws1`f&`1srY1jbK^b2fJ^=z+M&9uQDIWE1GyH8&H6v%08&UElY~y z-Sxa^GNLy7dDCP}Q7QR%I8w)lK3B}@0%~AN2#BK#LYi~}r+ByRixuS9a8%k=aYn+3 zs9;-izKC7A4b;5cenHV3FrZx5^rU^|aCLFMJkO%GvcDLH2*>pI8xpYn_Twxwz7Pf^ z(JixgT!gr=hnD8j=sZj$h2ZCW!KV{mYY@1pQ&1FSp&gJkdt}XTU~(?J z$;(S7lkrel?2fwpa3N%L8cI5+93fOG9L0mCcYv0J$uD1TN?yEsdV!lfKWt47A_%&O zg2r25?)Fm^CD%ZP#C|+QME9meH(;pH@2od;e*JJ%x=S?*Cilwyj*ko&@zUL$6f5dv zDA$)EZ@AcC%z^Me_j>r(3{^dgnVi)z!pYTc4B3h#y!nY_GZcJ{XBZ4yn~+{v-S6*~ zFO4M3qY(%sQ`PGy(QlN%B=(+gs>(q2TVLxQ*r< zzlQ9Y;OXFg`j8?x1JNzBcQQSCD8du_7S66Nr{Y}cO2Kti1UcW}w=FII9ao$iTzGL2 zxht-!`c^>`x~YnxZ4$=|w4bA{jQ zLP=p8k-S%WfMV!OB=s9JVD_n-!rtBqT%tVz?RTKVzEOe$dyIFVb72l~dYrrsiVoZU z_Cko;NtEdk9==Vx4Psi<=Kr>9PYi~`1O3#DL!y1|qfah`|z4G%buz}{R`XuK`5 zLwrc=g4(Fwgo;2^3P)21Rw{a14)yUQqG2fu9#%E_Ut9kk6BMdACX zg5CRpLp}}*OFW4v@U4=TP|4zBlL*&+a4U6Vn#mperf1(n|;(ZhEcR2A*=FohGwkvZClG zD%U%2J(@W6i*J$|5TYm;aa{Nq|JriVp~{n3Z~nm1_GHzE${4$}*Vvw8^hZR|X~!*J z%3+?@!3?TYfeq)JnxzHeB{2H^?#<FMn>v{qm>}@J`7ZS{{0Tn2?Uy;Mc-l=d{^PzLcaJLa?c=)8|V#t$l4@_u& zNgC)(CgFiVam$HZP@crF`0s7btduL$h3_@;nP2N7Re;)~#8C>^pzB4|eZaf33dk}? z$;m-tr0s3ryXx)3L%KJU8Q3U95J7c?*=h!uEPpyI<>fU+MFzIkI3uT9PLZ6NQcw$_ zVPi{1kwRG%U6qI5#k|yY!c)^u;I6_%ENxGa;JIFp2b?djP(JYuSt2jtgAYHhT`$Uv zl1VnqE(07E&|h%I!^354``CR5>c)?4DnGF-rUYZY2vx6_+ju@BXux=ux3T_m;2b$r zP55SYsy1Ycy!u{&-vtdX$0&qoURJ66-Z=hlBJ5DV`IXoOXw89^*_8;e%qKzk`3ZDk z=FNq{TltV*wUj*Hnn*d~zVH}Xi!+j%U@;1y>(*mB<<`5YEZAW~!k-yvC#x0+3FApj zEIfRyLUmc`&{ZaAXS+gD(_q8~9~Wc1^Werd*&vYnT!GEurG*>N$W?Aojjn%r!Q5{5 zC~56B;-z`t5pLn~ z=b(8?#%P3~*M=IQ^hr$W$(Vj_wEv$T6XXN>aQZ?}y>UxJfj7XSy{!%<@a+#8yhQ1V zZi`64QKw8?vXgDw-2OC9lK1#yLgfDV`05y5*Jc1-YVN!wQ~3g6tPY-5;5l zh>3b4WGGIRqwHTIZ3;b+TlqTo+oe(lgX%E|KauK3vzV#wl)Z};**V@=R zTjNJz-BeT6YR|bjMe7?JuTD$-k^TJ3v+i*uo#eYqJ4=YOL|KLJAC7gk*du6L z7Z^x*Nb=DoH@cE}TrWG+W`NlM^xKH@8@#Sux|cOfLBRmzTXJ_ZQ6S{|H;8XeM7y1x z+)kCut5-Ydq(K2W5#Nd!neO5Gko|ZLslJM{6j3Eojp`f-c{u}-X zm_2rnQwt^{R`<}!2N&5nV=8%$m%m03Z)|LePnCsLL93mHa=i5#7gwK#8`PE-f~TqU zi~NQSVE|1_h{X9;qvWEolM01wNszx6{oi}u_TP6%_>tCAmVz$Absq^Bd?J#6YEvQPvMa zm1VXLBoFTol#h!MG8T5;V&!&iPJObUQk%_S7H>ww!jy#6umamE+6jbdY{LmLQ2zC# z1++xNA#6b!#4wov10^k8TwgwDo@q{y*mi_I!nu$Xw}(W-(Lr%HnVYB_kND;MemZMg z($Mlzjop1f6O>nVXM}UxC+IwJq2)2fNLH|W+cGe#6)0oyqhQ3$XSw%Sj=uX6#locK zX82zVKlZ{r$tdvfYE?6b^I-gQso4wQEClH{`6>fNE^>v%Q_PggaeUg0B7!*>s^Em^ z_7;bk;yWW-NrzRxdXsn&(@Jy`+JNhMv+Phst8E%TdGqZDN^w}x4aG9!m9wmEpfWNI zI8d2t6Ovj zd!W_lnl%%-F`YpOu65yVwtH}iV`t#!`HydSLb6}cb3AgoE|4ehC9hM>I+J<6e)4v@ zt7*7s^J26-e=B!@nw2dH6#=;XmpYD)j^GiO{t_uqU$1g=JNJgnhoK?ssw`>EQF$cU z@)=+Np~u&S0g*Xh81C})X&-!LsO*gr5e+s>4)Q%KQOt~Ebuxo0@5hi#dq`lYJvH?) zR&Tf+P`$}*{b$b21_r{E)fq?J$B%^?T3>aG#pp1S7 z{VbHL41Osd9sh8gtL{nGVIq&}_&}2i#XzM26n^I$RhWjG1soC>@SlyM8FC(V$13N& z@EEn+Wqg!z?rcPh0{Ub>undG)w}KGrQ1_vyvNJs2Nc~Y1rK?onghO=^A(((RHiLHk zd5!&1+2>tSaJ0U3f~}x$Uq47an?E6ubD9+t8#5p+pNMeCMV90h{h=pF+WQ-)$m9uJ zKk7$T-&FFx6>TGgz$6SFbmdsIFlZNZ=A=YN@(PW-J?YzT;i=U?(|=b!U|?A$^Wb-WzSnc(1!4YV%* zXlPtf7Zvbu+JHbMo3HHBQZUqD=5_$FEOy!(Y}yC3InOiV;i(^QMm065$#45t%4i6G zMkBm8-pzroR+7*cCRouu!P5Tns^<|3l@PFX!Us+mS|iu_tM}&aykB9aT(`_YoFQiK z8qhg113-^DU7zq@1ddQRQ&eP;^+iQ%D{bMpxz{sC)T_H`u$xGjB;?8G7b*bzKY{-{ z(mZN$cb5F#f>CB-Wcz?o)iw|Zz4H-upT&A#8c$o-CUkt4f+MAk@o|8l)l4DcF;qdH z&Rsz{V6rC*ES^Wl>VRHPh!rScAg~{Aw!16tUR5ZbENiA;ZzfeE|IN(oS8cHL8Z13$Td2oD~eZ-N<{Q}YqHA0EilOcq35hGNVPmv)A+YH9z z!M3MkpZ6YLXV-K2N-*)`E0VRf?=;VjwOTI2c^n$CkpZ_*;-3Y;XePR8z@ZQt((}x& zBI0kUTo{?O$L}o{)rsXUazDST)u@AnF9PteDWlhGgO9iH?~TmbD1bw6@+QV*HVT%J za7O&?(W){(35W$fJ0wS+!^%Se&K*8wG7#*nvQ7P(7X97{HG^n&VnJlo!H6)3;&ma> zvzO=VuG`$?E(3;u4H%qLR~I?Uf!!g@FfhUi55M69rPa4yk>VeI=F1G#zW|$jKZbB( zX%Zrja3~=30q0|fr;h}?EWqJ=^#v=uT+WNe)&kG>iMxwZ`74-qa_P6xFpFBjg!{*l zow#}Fs&b+2-)D|{CrV2hqJ`Z}lmlivzZ=$ImI98nw2r_(58j1{r85CqEJ9j{F)US9JFbF)b+W2q4|kXOj?UEl>5`uN zv+*Ff1^V3#W;YY5X&SC1wERe$XZffiFM>O&!0mGIFRzpMtpu$F)z#-JaSwtfD{Lh1 z-bt(U!l@I&l4vAscwh`9XV+1x<#xk;VTsIAJaLp}k{f z8iA)#ViulK+IbTn`13N=*6T8#A;v|LqR5F6a8Mi@dvvZodA^lUOIQh%N5Z2mRx0>y z3Ftpaw8&FD!6)ayIltG+5ne~My#AB0R?5L64$9e z`OTVJk`tfLVg)~0KM@QilK+kUvI!H|SL5fOsV3U)H{a)MFn7S85oYN44Tk!dF?n1= zwyxtZN8B~Hyj`V}y^Qw|RbEpiZny4~EKjtL1`&E5dfD@S6>s$R=8o#yoS%tF+~HRS zb}iL#auPV(`K*yi`krEP_9AQ+qBt+1E7SJZrYWjESyFeGz3)Cmvs~^s)4>5~$;|sK zv4D{Dbaswp{_;JNu;}Nl!{g(qYZN1HtJlP}B%&o;3tszjs!?`t_U8bINOYQH0A>(v zgp(Y0XMYv)h4ad(puFNdf)IOl-MFgyKK^L@sGHZw9M@TuNsk` zCJ`|g6A=g&5i4hT>y`9P-FskL8AuDKsGo6o7hdCL^CC*{>Y~kQ2+c2(+NYKe>f$lNY>R`G6J^{g)gosl2Zdg-{*tGKYbf;NrM}uU7SRIBiK|v9P_Jw$^ z{~?VL=2;o16?X870q~7MzJk+}t8jV!C7ItI`PX-OtXq5-=0CDSZ3v;n!`uwqpR3%{ z6(R_KsT)}XTlg)QkAJ`MfiCB+ z8QF6k^<`hwU0~|;u~XxNhv2S|My|N(vLB74H)r^Vk8HS~b?pH%R>S1Auf*fa8>u<( zTx>x{C1=KD)tZKD+$rDa4!6g%EpeScBpBZFH>O$43KJ!)-Gp|nN+7$ zufuCJoy}eNJwmsA;02QMb%G*_j)B!6jaXUV77xPt(>NS(C3v_HknhiU&EYkrZ;II$ z9p8-=-_ixp(=Z8%P_(~d57~L#m2Q|ct@uRgXH-lQ@(18pv)`1&pFULvw%(qGXVlS+ zz4038aGwGVaROpg?c?~~K6Ux<;iL7>@V4+b^?(_~d!L#9rcX-dOhBgQPn~1+9G6^G zU!>coQXXBA+r$fTPk{b?APA#Jr3)uMj&K>1H)L%;N#*?>5cTd8Jn;7Ms50apiU ziBx81;x+IYw~-KGB@Ja8WMg<|f0>%G=)3ph;CQ#^&!0bL$Pwg5RGh}}MF^Bu=Gk3# z{bFtM#X#5N@F$tvRi~%Ux=lM~6A~>^2N6yyivzqaC)bak*F&|+jPtY>mBh1qu8cRg zY-Z~m>1~E-c8;^BQJ3ou?$UCa(gxLIw-2bToi2fQ85Y4C>3Fj{_;*Kb^g+q`fiVu3 zkW{1UavcwFO~@6y@BgK@758T~1^VVDC--X;*N>uKnmq%PFDwe&i6Z7}LXgMn6~`Tj z`bs~x;o+s%i^CB|w{C5Be~zr2%u|??Q^jQb;=K-TP5=J9x?@|%P2IQm3gjhgj@5U$ z>Dvc#wFX{2QzPkqcJspsNxgtu))C-)NZO7V#QIn$8meF$Y+2N|z`|Pm$tOZy`f=Q% zfX`32{niiquf$vr6SVFXZSwaBKOcQMF4HhC?{TQJsN8S5hqsMrs{JW?{rlx<$nX^b zY`LoH8Dgg7bJC|zQrT|e(}NcVHSGlDxP?}e07?6|ux*6A=YI#h)NKfkKm_&|S^4 zhr5!)JuTMrCE)bn@%H7OlPL{NAU9YF_4D76@e~R}YidS`iUNbyVx~0hg5KSfhH&|- znA|UPI`o5#@+j@%%Z;8+_Q}A6?J2$Tpq#W@)ogm`tPtrZACA+zUR8R=`RnvwABtw^ zRy~UzK;BV%swk7&=-)Kp_x|U{lU-i~sc~{O_stvuLn21G@fFPwqqmM|0_UXQGg9VI zqj6QHgwdVPMJgEc@@UJZ7y(ht0y-!rFp@i&I7|~B-DoMiFF~pLUE`6LmCBPQy#m5W z$kofh6YToN>h(^(M7JiCQgO$l%&(&H34^Ufw6b~F|t8@Kj;+7 zGgl+-25xuD;!eSe&ve2HkkAJ&k4-xstNe0QJ4t*?67nxMcX^Pw=RMJ_FUuFV-l!mS#LkE@7%go0+YUT3=* zZtA-iJ;r77kjDdtRgL_3fE1~n9qrbxqL~5FbJ!Y?lI?S0W@S`1`u6H{@2i5|MJhEC z)b_0EdyoH;!BA!E{?A_y$~O)j03K@mkQp%%OdpX;usFu%jkyAGk{mup9ZA~Xs9@j0`epQ=~aAXYT`YmjBK9A{;I#>|*Z{n@# zl~8MtQIC>(iviXQ@EWKZz8z8Mrca@pRX}Np-)!K=UaKD zAFe7_fE3JamgGvDu2(jYkrZAZvXx5om9R!Fh~wI7*59B+i1LFSHH!0XRWvQekP^p` z&dFa0jKK0$ugB6NExn@R)1l&X&WqKHw}?kWQG<2Y1CZl!KXQVBwYgBgry~7JbFda? zQU0mOfW~{bBUL?H@&+8zIl-DK{3tZDMfY=9X>42bCuJWF`}f+(qXvT_qxCQmef+hS z$Up1G4;|8OhekK7?g?XrROKqboyJ*RRRP%Xt_Q+hXBL~4N@1W`{ zB*&ZF4`k_%7H2A^m(;n*lC0IoDnUb;|33{U>nh21S^)z8}gjN#^fpey&Ll#s77B!c&r7G2Xt`s!5GjsR5D z1fnvl&8r0Zh6Ic!rDk|jtCVur6^42<%ouDYA9)^kKG+9Rb#Y)M|Jgc~1Ydl3d9B&p zfAP5F+;WEi>2zFMe&EIu7EY<$pIDibEP6zKBz!>-M)5w(l=-`y|^xI-_+L@Yn&flA8&J9h)q~Q;V&=N@AeA4VeF1ynR1CT57 z2KJ2%j6}bzy`Fl;mq2YF94I1&+6&gK)Kc*UVeq8FQycGKBk>V@`W38c32-$Dyz0>u zlNN1VUTPx%AdOCEeN&I6y?@5aagUlElp3aw}JxRXt-$VbgOJ1?EPQdDs zSsyAbhC2_+SVn4ixIddY#hN$B?s{8RB!mVe4t;07QXwJBv#><`kR@imnGbnHcKPys z@ia(aY^(RDIL_Ioszqw5?lZ!w19%bJbuVH-l*e(0d_}+Qwg-ytn$b1xp1w)m!Knj{u8Xm_-j8d4_nrV`O#n-O;CEul)?vl&cz zG|$<-CtzB>t_n6q4^X0SlATD+H21T|s?rA|-p+oABx%kA=r5*6i8oR{@?SLlpLbLO zsdeF>A{kz^tvnrP$36EM*#7PGZ96?_jnWvPC(_aVE#euNw)J_^B#c8f!>BWKDzRID zLsrcdy4pwqa%mJd%_yC2eQl{i24dK(@D*1aX{7CUa=nz#<#yzA&D@ zA6E1M*3Vvc5KdmGl>B0Lyx?yqO0q>Ra0mEWF0PMAlMS56NWBkZMnorc!-HTP42+Y0;%B$*l(!AN;7E~sm)#acNtf42=zk6z zi`#E&w%>XkPwf_nN*|q8ae?1Dg@UsJ5`^avft-h)vmuUXisz6UkwC$0{+ zb?PL&*+G|I$s=7!Lt^>K9kgw}eP8-X6BEnhw_5OKcXLIS!H0M}i4BfAA$HtSjTywG z4ku5SHzva@wmOL4F^n}@CZJsvau$#R_-)^?hqV35QMD*bcH@elWe-ykDlH7pXBO~0 z0_d-Zdl{DVOI<}5S8F^}0p*W{YNP}@r=@ef2F`6A@!4QTTKn%Rh`Do>1e5arB@D2s z8HBSfLl(j=EGa2DqPz{D^w>CgK0d*+U8+IYIBt7?_lJ4Dfy8~$2?dsEciXXiUvWeI zWr6qyGv3fbWzhI%)~XRYgE@J9iUi{4hGeC@K%9nYu@Ge+93cNQk9&HyWg5!L6#b(#Qx>>*VKt>R!S77^E+|RG(JGMOJnNO;>UsF9IV4Q;lEob$3tf$9 zW&1uq*3RBn0N~T*uyO8boou&d{i%KCFU4+1*Y&%cP&v@wr+8q54w2HNd3BAlzD)l!X|6QErW06OqIs_DJ=v)kLh%4qF9 zxBm})alMj<^M~1>xbNZIaudAJtMG`3h~02w-xEJ@knnPT@N)9tU-0kkH_XC&569%s5d#!CX9l;EAvs!F zR;T@QCr}Q~LRIyj;XhifMolW#gA|-IykZ7wnl(2j1{9pP7a!G#q*mNkI(n;o8bnw7 z312FQIvhHNNE)A6GJUVw>L`e0m0TqN61Qfzb3NO?c@gA70b&d=I(ppR>{(7KG}ga{ z^YBCJF~X8Wm$Orw8glgq0re!>zfkl&SEf}BjxKE8JN-e&CRMRbOujST4AYqv2s_EQe3k8RN*+Kb<#W8&#rX<_FuKEvgXm zEi*Io4CQ?uW$Oz)a8B?3JOX))Uhv+X*7o#ihTKsZyU)~IzO+!gbmzH zej!XVC?&`0-TmOV)`6|}sD1S7?3SMAG>)5p`Bc?w@6e$zu=ocWMtZXNd-C5d2>kHk z6&pQUNA>E0+h~>MiI%u+0TQU^ycz4YF<+-F;p49vlU}-*MMZCTf%jm`AEL^#>}aBk z_QmCKA@--&SD^X3d!pq_vqX`6X4{{5LILG=QV$o`;DwWLfN~D=e_-&xJc0{!=-)-R z`pS?lGC%F*G3Vui^j~@C!0#A=lA+_dvhBALAUe#i_cNj+{n^W$B`xhY_kK7LZYwCD)AkCW~8}+0_!r$k}S`}8d>gM@n|GA}5!Z z)t2kT8tj-`n!X*JV|9LmUh*B$0JE*Q;gQZg|M~z_VY^b**n{}2y_JsiF@e;lB(dfs zCh2)&9J8^~9YlMX?r2X6szL_5j=*-RwN>$cUQwer*P7=(O|u5DP!NW-t-yrq#Bz~g z#BhE`z6S6F0aIbvlzvM$oflb6Lbt0;M|WN9PZ@_-DA!RntU8+d`sRLq+2(Z-R_QQ^ zy~gvxTyE-jEz9KIH_}T`564HwzQ;!)WqhN*e3P|GvS&lm6nb|-FV`Oc&%=UJus0POC~4#~nMr%NBC7bV`dAfy_*^hgp$EhXeW?Mc=*;3>xXW&DDb~=uvWz zBrV-?Vf4oX1CJBQIKK|j(|&YCdH9C?WLMv&HVu>#? z4nK(=zmIoBBPJ7|BE~wzJ7G@7#CmZ|q9)0`Xb{i(jb)*Mw+%^iIYB>0By4MJfcaBO zl*XcqGRlkg)0bCI)dqB{bHwoKZOMUkD zGYCK*#KwiMZB9O5j^J6mTDeby_?#a@e6|zkzy}YV4g;e111|zM+x(r%v9Yl#Y$+QR z+I_Bix^tgoKjR>JWY4i}1p-N^Q_=jx#?Dsnz19;32q^C^=_x&*_vl~XJ&035B(K8# zD!w8wV?SP>J8!J8vh(}h_Jn-en2)eRMn=QH+}t}FRbeO`GC%y)sa3aEr($2*tZ8E3 z`R7nK9vjqatx2>BsWMspR$W&Ie-U!(Hul_jlW9j{*VgX|M>6S(G9xQF^W6#epd-C{ZZ1xr$Htm$5k@_XK-FHgEK^AA%AGN`5F+_ zWwaU^=X2W&%mJIdl*@aC+&Y~{AC~zpV^8iYd*o5D(@iq?qr5s4Dki8$kty!MAcsRl?|GNNk`6_L7ld4RP+SIC!vfMaxOqOouxR zP>C8YpyP{4CL$V~no6Wjtf^sj8Ex&6wR)r~T)+SrQZiuoGz--Hp1wqDNWXzUZR-MF ztdl%i(kBb5jJo&E({^~;g%R_!gPOFJk5CHF_1V7(ybG2=irGq1&$H~#;V75U+)JNr zEpHGgtG{I?PI>`>XOj&2pF29+I`dsHH8Edg*(%`XMMhg+=188k;e25`T1LSAgiO>y zJD_Cu>7f1qNx|DbCrQvGqmt+2o9>T)lj3a0V1<~Wq5U=ghP;jc_Kenh^J$w%J>k2} zL>>}M3XfGd^j$b)e_TV9YCIwYuYhPHqOm;5u*guO!HEgwi^Ud~8Ly7xfBH7r^YTI{ znF{_6=^k25e^(wyS3b%z3N|rBDgm-*9V-tV8bY0865Zg-CxbT@?=XchgizaY=Urof zIYbINEcO?=(|wH%!{<>-18pr+2ui0t*7Wrz_ruTqP4Ls7pGA)$SrXw5r%lS#mb_q;AjNOBXMkj%{F?|M?v~->D%VR(1+vVsXa4i2`XL$h_|TPV4a^ zOxw!)wFf607(O13OBsL5z~`(_w-!6jqoqX~UfR_VNfUnm-+>(3G*d-4cmsNn)Wk~E z$|T}5&4RX=2dFvQ14++c*IECq|1><*fj8?xN~jdrbcZYdFRQB5|JA8pH#dqHZ)@yQ z+>oCPNtg9E(Axu!nb80HVgJ0M21*wj&%cZRzIy6aX>!#1zYnf6Gol=NTqvh$c-%|s zcTBsn9lc9ZyZbi9gj0L=v_43!WebOV694W->ZoU?Rd`|mL`qK+W^gJblH zIhJiIv8sogd-0F;$zFC267@NAD}e}ObarlO4;q16W6+qtr60uH8#=+SY8nAo7I3>c zv=pM}G_{hxGW9>>VFTH7DlvV`;l1Bkst&v;*f)HB%*Poe7yU6?}V9M{q|v97QKFdJw8s*})9{#BQSCiJME`Kkt$)$?hu zts$-^;nTbhR6@fgQb7#G=}huaK{Y@-LZ=p@J`Eud#|RU|4^*FPwFNp?8>fy%ROILw4HS@>=j2X$)>7n@YjP=aHr-fa3s0O(Rh(^P2K!tRGzr%hu0fcAN>D+w`9ZOZEQ{vPoor6Hc>^^f~IInywF9wu-32i+^^JG zztCB{6n1?|D_@FlR2Y#I3p{;LXHAfhVXVPqv{n66ZiQ+qX`G<~EiQjwT&@*b`Zu&( ztGGNPv@`=y;R()VM5-L`NeKkyAs9<@$cmjF9Q`eKe-z9jY%_@;1!>{5+$Q@tXUM}C z0yN;l1<&qBc*loWuUwUOUAs(@$m;HqN#p05icC#zruQrjbgEocMzILLeCx8Gh8yqH z48f0UIJTP&}5kWD4>mA3TngP^8HZE3I# z+*&$%eC+rs|9PMEf1W@9w8$_Gg%_oV1KSeql~b0rQ~nGj{AtV`9;u&OJ4)4qj;~*O z+Jh=OJ>(lx#UtCdK+X!4fG@_MN1iY4;-qV&c9LTx`?9T?oS>-X{ML;4M-t<3EZs2B z$oQ*~`d2aazRK^QXtCSer?)(0wQjMibI$R5-<~!F2OwJLzMJCs{>HUi?7kUT`RH92 z)My%%+;W43;`*)EQAn+bN#Adn5r&F&f?UvXK8RQ2Id(3O`|zG}^MUpnGm13GD`u08 zc?%Z;#TMZFvy9}hProe^u!`A7epS*3u-V{JunPd%X20#$>%CnU{O^9s@aLrDPDx4` z%!r--I03Jn2vXi=k7P(B&aztD=Cr^i;Us-;)I(PHm#uZ}F|_cO8VZ|qMfjh4?Sum< zfw)3N?cPR^B`Zj@%O1c+E0Yj5RHffZKNd;hT=6~*+TP=0istW0s|kOa0W^4M14`%u zI9`PWd`H$MK{ffI|E(~d>0>CaId=~Y4IK?vaq+55ZKL>KJ{f3je8Z^3Up{26#+uC9 z&F^-9YVH0+GJcXr+gCxA^k)wyfXB6txhH80AZ_u>GFnbPPys0;dL@o(Vf(sVaDYL> z%t~dlLW--Nfikb^;VY0NEP-Ie;c3m}cUkKA=;_(7F)k$yPSW@6SqE(cHQ|%RQa&JW z^$X(Qmt%T9`}*hXT1uNB><;gKZQ^ONud6Z=?KjikX~<;G@~_pjD;RUrrj&YlNOvA@ zb=yC5$%-|Y+_AiB5usZ0492adLNt?9X|nYhkb+_rk_B5OG?vfISpy-2h?XnT9u&m~ z-_H@wjbw6EHr2s;?>PJoL7LGIWXwY$G6(R5c;%mL{BoZkz_+{q!~IcS`DeL23HEj< zU;u)6Oj$RQdZ#_5C415xuA(HREqTf}H2Z!sGclUhOg|F}8Cl?&LlV9i3GhvF)tLP% z%~3cfQV-)2H=g+fps}M`HB+F=6Sf^ER3hP5_-EIPkG&dtZ_czsL`ytyIP|w4HsS>2 zs%+5W`i4StFu03tv!B9HQ*>! z#|#`d&4rlet`x@e%aqV1Gjd?WtK=rVi|o4KjS0gqnLM0!UZD#x@ZvW$f_coE_WDE2)BP7MF6`7ozHhs?I|4KZ2pjXiB&?l6(3nJnn*l2JHS;-78*m?4#DXfE76rcz$R%383;MIO$9h%WrdcSOL1zP<4-LSFr(Ulr!};~;nWo4R8P06ZtWw>~ z$1`ounYcu~WbT4UnW^}|1Mo%l3V3fAFw;_zb-~@SS%>|J5dOb)a13e|*|f1*a(kLg zm~5d^L1I@D#uVMJdYBL!MOU3MmzlxTvJPhP29&yc>bNyKw4#$@sKxF?l~MW`$mcqipT^fr_(96tYcba6Z0?kzJy(x%AJ=n zY!#1;whWG#+0iD>O8wz13c)W2Mq2e(7T#?GMLd5x_ue8N=13BzX4f`ZtR?VovCf$RFZNwNcGg7#CF%67r}k4^Awo zGWu}7ho01EI&jp~|CTKfU%EN%!71WZL6x(LuVq0i!}nca=~!S1lagwNCDGQ|0Hp7S znZoEOXI-_JVnzQpM`Z7Bk^sZ-8P7^aHq23P)&k}7F|0ia!~bmqutS3%UJH-B{WYf? zXTLE%%Z zQHfk{y&MLj3M%zmROwp%0>ljk{Nyo=1{8bF62JF-3PX69T=Ywn zWTMm3e)ZnzubEGeh12^&ZPjVg{YX1=B2Lt87vv}3chG*@M%&tjj$v5+St(QC=zKm= zULo`ReYHl7i8m?Y!+N)7p;(nW?9{GlXFtw-+Dx0@vo_Y?0gzn%e<+VBpyU8ej zHM2-^6)uA3JP)Xk$CSJpgTr(HLkvkD)fHQvghN$4D}&DQtzY*$qOrBOAL9xS2h)LL zpA40IzlX=wycx6Ywqc(70aQ^VR)&GE2+3GaNs((SXj2I}5@a{7u4>&c%-ycAS5uKM zW=J48;I7;A*TXUITp?}Ol%$d>awWurTMN7#U1Qn$SQuEGs=u7Sd8KO<7w=W5&EtL| zI&(6`vDHEGKRD36e;d6V()GV6d=Amc24K&5&v~J}2C+{0rYr~$GU%Pc&p=NL0)CRl zs-=s!E@EieBaTedB-hI)u^Yc}77K1_mN79WareuvR+p6C|DI*_=Fby?GdB~Dw5-C3 z9G$MERIQW!X9zkY`(1ZRazxs2A~7+wuu$|@hJ4zXCe3#TUx}+}LtO}pY}4wXcm;bK6Ha#Pa&tG&a4hn!EY7W z$7^zc&w=ihFypD6m_xPYCxKO18CcPQp(;#s)dgW_Q!A^G?TIcZgFW5eP^=VqV@p5WNqn*i?Q&n;DPdL}vx zqC&yrj&4Rk0Ih1`h#C{3QN20+Cd#ZF_LE zvAWBEa7Q*Z!vryCm*L^U&8Ig}9@HETNqYaIG1_zB z`>+ZSE(;$}i9<6cf`8<=WCPcA^%*T|{ChA%ABf|7vp-1ag@#Pjh?6IEt5}k_ewIvR za&xPI^A=8q@grx7v$Ga`hD*7yaL8q>@z~zbj_QJ3zZ)5pN5=)^E9!iJ$zIMM^h36x zrCHOeQ`_oRb*6Rat4(Ez+9Ix0D64%7=WsXB!I)mTen&{!tREyf7jg)#Lx$hkfYWM1 z-n1U@Zx?C5n*nu=@$t;H_#t)d-!@2u)oip(Q@I)kT|5gZ|MMXW=*aY64GceNTI>SU z^9OALyKG=D;bNaHvUh=Aksf_}Vl%BPY_eU8t$+@Gz$)3^_OSBF+;eVu>bEa+9?k}; zaYNgJWMcMAWB0d`6|DdQm62kM4YgS=$mRR%wAl?}sJS;F+GGcn<;+^!d=!!%%Pg+1 z9_-{e4DMp$NUPs)c0QYU6_B9M3bakZ(1L%EVigytakc8rwLJZ)hV{KNuoNZrXVmap z3q`fsOQ1=C%s@dmfmI^M%|e0mIw)r&)tq`GsS$&~ z{%>Q^P1p8B_VROQW;JkR!;V6Pi0gtr<7nL~#Cyztoj!PMsFwdg&Up6AQxhH&M>Mb)I6Hm1UU@U(&Uei*PG%J_O^j%(5p9+Z*G zj`D@q!-=eEp|GVQ+}p79V#aJ*a}>t|6U2abKDz$eSwYs^ z+k3vvh7cu8Iu%y+UmvkzV_|DpaqPaj)_7VaU{~=L3{ceVMQQfa!e{(QXF?K&GF3)z zCpim;wujGew*d6y$!C<^iNs|I2Q>?fQOxPFQqz_q;ME|EPMT4j{ydud&pgomt1v+! zvqVGb9gUNMc#O^gDn-SVnA07W-->Xf*=BqR4nzotBavvMgy&Hh_BRO2vOj!Ls{9=! zjz0+Hi+IA;6}{|o1ZvoGAlw21GO*)lPGoXZA7z0E9C+&A=?|=g)eUew8S>T*Bo`MK zunVl5bfIS$QHh94%}8Lp3cBQX5~9LpcXkB_QNNZ@J$>WphfrL2YG_Z9?IV@%8tZ*B@)|K+I;YfWQ!|la z5+Djq^1YkBM)-iT;8lioQ3usly1>Dgt4dFkhsA|z}^Q@Z&3l-!3xaMX=Z@i>& zSVBWUO4XGT^$hg_OK$Y9ja64$!$pVJ=?=d_U5uw(qey_F`sHTxSPr@&46UAP{iT$0^YE5aFY9^|25AZoJWcQKyf zZcnkOyMJVsTNNkwE-1-))SL)eMRt2r>m^uN*aEs_e266X5Ls-1cCK&db^U7FZelMDGJ*tF>SXzC9~iq zisbm#Pr5zXN?tE|S`ObV`t&AGbO*qzL{?c#hl`UWCm-x@nW%>42>P6z{A}ZJshj|Qu6%&Rlo#5$Tqv{&-k}U>y4TlC+!GS*PJT}z&T!=9SfF}?^ zChnKFLM^Ia=1mYBExD(4r@1ZGE`3NJ-&$+tW6Ms9|8-$AF*{_@@pjjD#wpp3#rVYo!r+p57nWLxk7h^Y3B~g;at3 zE5;puu_(|#V!l1%os}rqC?5J#ti0UpAgVRIKA~D7Ajtd1Kq*8SVq0+MIKFoKD%Zjz z{9yT3%HDeby5RM6g&&6ORIBwH`D=fJN^ob~oMko7`=Q?x8lG1Z?B_iz&*WcJr?P^# z3CJI&g3_ihK)x*iOBJ*sqr%r$h+kxEvn=uOr`n!Y1KBV+PIL2d4{f_PL-YS*Nky|q z&g_gu-`LbzH<5pWk3$NEV+^6jqbV1>adpg*KfXmwi(&hDrfn5SJ6i0llZRG5J-J_r zdYt6hH4&mCO{Dl63@>nF1Zh|FC(ue0QBv*zJt63@a_i6Wpe+I0<<^*x1*@MkB%@nM z!8p+|F*Rnx1lNZPymx<=e;q`Tzi>Tqzm50p)u!og)7Ve~)`8#=|8wzJ= zBVG$!e~(Z`W;`oh#&f2;!)*3&$!J8q-H3LmE?;ozXK_i?HS`*izwKzCN|Y3du!|-j z#B^-s_gkU6=%I1L>fNGgWE(+?AIj80*d<(JE%b_8__CXxXX zXwKrHasTc0?$=aes}6yub^N=FH_=d_u~(D*{ubjt&E-g`>Z2W}(hd6M@$8B%Q;d`4 z6l=TDiq1S|b(lnJ_$02Z^qG(M~ZJW9*j$7y8vr>r> z1de#=#TJAbUy#DsYcleZ#x@II84sa=t~*Ss)5x`pUm(MsPttq=U;-8g8#*5#lLs@I z&u%^738lJlb!s5i$?J0e^+icDo#jvT1U5Cl(z}@FV*zzM40<Ko<9ztu`>Tx9)V~qr!`0c=#ChU@|LHR@@-Fb?nUTpE#W@{l-=zaRI z&&c=MG*>eHCU1W4u&~?7--v`j9Hj-&K%i59reP>z)jNhBr=HVh{QnpoCP*iOvUv7y zge16iHw0#LpJ~0_jAs_+vB1vm^ga<=#fPf6> z*pdq#KHDsg!(WsZ{QHQhUE0K4Uid8Th-I2_eh?6y+~{}{`_STjLpm?qnj@uIgga{) z>e^oV8OM|1P2j8yH7AEtaF9vi=M1e$_3ZMro!!l0pXcB7o|n@lWu7z53pkLEsX0@t z8>!(L{l@%`t#X%_#7u2pn&&X9oN0A6Q39@9?HY|3F1SGR#P{y`gN zr|j3!mSU!pnq2PkUh#awK3b|VgE5Vz_=v1vU5r5>7iV!mCVQ5^7cZ!YltX6Z_}{pUG_r+f+yW8Afa+(&~ z8&V-foyCtaKDm z_v1&Fhl>&ZlGG~2+VwHjKUag#r~(FP_l{j2lL03Bx)Im;5$Gv)W#R+!Wq3)TCcdAUGla@i1U_r)-Z^ zVd|qd@cj`L^@X7#rc8UIt(~K_C=VmUoiKO2CMTscfL%4^+*J$6F(IQ>*?# z56$J$V^ftYX|ey7^tmXNJ%utS>uW^qQVeuWRJ{V9Zjm zt{rH{!=Z)fumuI+jpkxXk1)3qkjDC&QNEBz8;#>_4^J0Qd@-!z@hUN7C*k!E76cq* z+=R(Nwd9^+@{j6~z3f7eyTpNodMi95BIDF|3WD;$ED7=GZ7(E8>wPSTno@;fp-LeN zvLzzUOh%!6H3p-+WO_2Sa4$|Leh=X*P@s}TE+44tip~I-Z3A@HcaY+Il*etiJ(iX{ z^@W!=>*D%P`6qLrXRT1T$8pR#JGV)zgLDy@73|au19Nk?fU^kVVsiokU$@Mt4Q>{; zA8A=Sh1xc&4{)*M7ODnOw!^tq^crM)!xTavY93V@NIt4^!xhjHpj;PwZimEEVJrwS zY46wvX@Y^jpFG~9wqtRoE-|>OqrXC5)NBs8*ag^xIAnrHyE^V=Z3$WdwMk zRv)iim_N@*f(OTHmNMNT92@cpE@+2rhdW9TRx*~Qp0P)LuS_@q=aeZ+2T?0(8i^{r#4`v$JsYx=tmS|MCWJ!l6brkjft&y z>s<`BqG4C(_z7^z2BEPomwnp)Eygs1QXmGlBlijkNX~D=nYlBHES{DBg!C*%K=^Vq#w2VbVp$TlfL6+4pCz(Rp*`RsTq7;+;@KD3TJceV-cQ+_4(o=6S4os19oOcB0 z(O|rpf5&B4P$W)d)uV(P9Lb@SDxudZ|4ZcSb&>jC8+7_`RjiMdfkEK_;5EJ?g-~!B2TQ1kos+dxKCk zQta)pd@aeZ5ALfyVrHLy{VB36&2ua}V|AqERdVw1v^A!XXxB{;ujB3=T!VH{(H0k; zstZe%8Y=B4zQj&z%LR_NPk?WWtpRn%&f)L#HD|i;Z32nwV_D9|zO}wyxI5jCig8o{ z*n+ymFTqH#FwkL~7pElNXxUAxWuYwBR}N`Mm75VB!OuB;<8 zc0TRG5+f>Aq+P61;o{^ITA>q4OitWvoT??;?fM`crpN!dtSIER-aEzZce)4B@ECx~ z9xkVCoF;JT@JVYXgD$DUnRZE1W|8o9Tcn`(JquW8e>*>|e+<cE-JEWgX9n zT5|w=UWsW3uh5P^pq0^x-W-9Wvv}Xvo|EZBc{f+xxRKF*qP4Al&61b+V#<}rGHEmr z5dIc7*i9lFG!8E*g9s0maT+K_N&BUE-g8Mi!vD^5cRTET^BxZPy39Z#|Ag<=D9(k0 z0B_XT-|)GkJ}vurVJ_(+(I`H;-&+qcwf0vv>3I*=(#dvJcxeyIBc5bWDj%Jvqo+Z#@!d5AL z@H(NGm_FdG3y5}w{_>INdf&B2DzTcl>ZC%K@aW-;01*cfC-f2n<8=$$)*VvP>_Q0O zb)lDm*0PeumQqkMmc13@eN$rvRUhNuUtINaIzYYGWG$Q0+z~UVfc)2&M&5OWW!Sz6 z-CqP#IlaIT;wfiZj-8)ys@V~o^NRDOwa%NUMjZiYx)(W%yqBR(%kEQo#x>z~(2vR= zi&WNn<3z-jh$Jshs8HVoz$=dcx$;5x&O!aMcvWi~-qhkaeO0gCB+LpF7jB16FXcWp zpGbSy`$JD1N#PQ##Kx?^VOm683|B6jgScK%#HKh@m1XJX_BmHB>} z<;l8fa|(;=UCLU=bI7TNzLbZ>&=!VN)AC>=6o_5l75-=x^mo!KS%Zm%^~c^3qj9VRP-mt}A0IxpwI=u_W0zULzk=_OC4DIo zG`T(d>C1HpW34%w{X(SQGg-S(g6>2x_Lob{rxx+$ha>REsZv-l;P`O*bjU=JOO|96 z?E2FP$)M%-?|=q{{pM@S95IyUKXgiG8~U|$QOO~z zlkM4;Xng4w;6~@R=S-2-FwtL$nw?7{s63|G9&bCsQ?24Nhqh%_+b0Zv3Jon9`woQW z%437%nHdqjybZ^@GPOuM?`tk~rn7~Ofz)4WXFa7BWfPBn#Do>yjdu3~jfQFJT-dXk zZE5dRDrdK%*VsD&nJML9H25US->W-b!4boRd>OY5UhByHY=)^LC>SL25_5V_q>$cv z)^=@j@=v)#o(ay*jjmob`X!<%7B^i~(!*vW+N{Mo0Y5HlkZqt2z0QJqDF3pjeL;T> z_c!Y}jzTZ&Z$1j{Ape}cq%GN&V&Qq?*BERkYfZ?uT9pJ$$VM2IaGsB$EcA_XhPY#`|k<0m~d-GF3m1LF)mE_YVAR18#wtbmBm8DT4#Ya{RD zQsVj-!aqpKVlTT*&F0Dd?L53oVdjm^5(qm%!AHifc{sjN{zh<0TIG0FhRx~y%(E4u zmCwiX%woh>kqNJX=ziTPr)&sl3rc zFwjEU0tw$jLO3|tm+7AB7R>o*h<|~NGf*HP5+wn_x5R&-9(b6q3$;SUB?cBt_PcOC zo+_lr^~rH!Cr7bNt^{E*=>~|nO+mwl^~KKIg?i^yb^2IOnSMWW$u~ti7?dOGLNW*q z6*5LwIHs&+!dm{i54etQBg7kBTYA33qPy1V1Z*Cafpu$|yw9l;&--=1IkEjM(4)!j2Y#EI^<#92Y3Fc1m%>HgH&44`;t>q> zO4_-zkOkiPi8Y1U+WmNo(8Q&_rS0#6D=1L52m|;A9JAm80J+R~(9Ju@@J*gai4>l7 zHF44F>Vo^~20O%gX?`vDbx2-VJL>M*KO~SnKok%xDB&v z_?;UcYYEXO$Fxey#w1RxXyW;XG?I{CXsdYo@5Sq~(^P19RI`D?QNVAXh<97 z|CvqQ>NoUx0b$3Kktx8O1HwSCwh!Jbi zs!@i>UeRqLX(mT+q}}}uKFs$P2;U;8xS`?mqbH{0lU#k4d4h$^-F}^W*8Fh8f&@KI zb!9Fu@6-wmd9xTY43Y&lNnaTCbMc0li=%Mjx!y8RHW4xQJD2JQtkEDZP3s+=hI?`+ zFZ=Cgvo9g=^F4$y^j{wGm#A90$-^_{zS~AhqDD$ABZ_RKG7++D-Le|n? zELRr9TOZy3Z!#mUM|u=Js{HIqA#Tm+C-=y{qq-tVAMyk;3Z%miFM>6O--=9VknhXl zT|Ght(GqpfC+b<`Y`zxFTJLd#2tTkaV;KCK@j9Z}ZPqcnn~wzlvcbz>8%jyCWfUn? zfsaVd`)Ca{eXcKzg>&&S1N*ag45A+%nKm;Gf08|`HhsKuCFZ{=ZT)B2PRAFZWyOX) zXHc}DSN2$rVM5?HEGx6m0;g1(OU?XQxjaji*lb(-xZ&FWIqS?7Wsz=P<#9hN&e?>l zKzktvWepOI4>L@D2y?|8S1L-x?1aW z62J}KxMrbR2fRk+=$c-b|j+;}kn0VUI@clQHATJFL^KGh(9o1Bmx>4r=@Ddswfx z<)gJ&9rg6sP(N_e{YJY2op4DpuFq;727u*0tyzP4OZTgPhC%MV6LOh&L94jbgVWbU&+F+I6Cd7{lU6o;!zbTKaW?< z)Xf)8DA9Ls=|^uPLkky|3RJyX#RRDHDL|3{zE|Kmvv#);wCHlwrr1`@Q&tO5kx~TP zPz%%FLI@j`l2_Zt^9|18=yI<-p4pFE$Ew=>Jd2E7Q3RP7xwZtm)n1S2{4ct zC4UcmCV6S?J4x1!aFQKVcrc+t*iToz=)bxpoIkK)5l^Y7_+PrbE@eyRSDK=h(j8kT zfC=(^qlPzfBgF|o#2*x^m zmtV99a~=u6@`naEAu>ptMY; zchcCLozr{(|45bH*Hy>$4dKq>o>}Wlun))75b;T(5hK^{7Moo5w~cqj&d)w+gnysE zzx(&!D1o_ctU)CRf%nPHZSAXQS3Z1asX#1WDjcc+wc>Lx^I~LvU1RBx&tx<|UTrr) zG&>rfc+kunaI~k1+7aaV#UjUU0O#Mt#F#Q*Tt?8~Vi*Xl)#Z`0(EU|4t6rFL1t|o7 zRmQVA8duRgMe+Di%9#F0;NiXFWI?fAFjl*I@IKwhfrxKM+L%mxQKDJGe8evGLAh<= zmNC0G?JwZnl(mA16~+Upb4;N;w6S1!&- zh3W8moyAIoiW8a);T911oqY@Z(7=^;!F4jhg;TLi7=P}>@h09q@?s7w zf{!}jdWeu-n3`0|P|xSoIuy6v?CbWp4mxRp%jTJVpFepJb4#lJ0(^-g5%ZXB6}PidKtC_s@4}P4?C(q(d(zt82h29l>#iS@8}G%1M5a(o*Da=SqBYtl74sL$)NTG79P#hT(FaAmNMC1E42c){CR{9X2A$qv_DC_MEQnc&c`nR^fqaL!m9EcEgp% zB7u$R-2UNkJJSlPTi5MD4Hc zgmtJ(V96z`x~^xzoIlv<3_-J@0lz0N%mQCd~5{8Y~+vEl*1%DZS0QDe6) zB+bg2eTj3L7CIKDv}hjG4>hh;H6x>|`EvyAhF!&v3ck(~D>Znjg)WFaK&;OX#eCsu zKHpbsqZlo`<{JOT7M*3C9AwmZN&eMDYdt>zthH8b5?*tVSVerXPHsCg0<1~n^$@AM z019AmC<|3nh4iIxYV=AL%;%As0C+iR#j%bfAlys4C)lq&K5?oO@u5ZEqyMv{0^HNU zG^}Wf8bB57MF`bFP`GApSSCxZ{n62^6k4mw+fKXdR;pCdnsi6fxJfht?^q=Pu;)ow zXng>QH7e|vH~+ws@J12tub?K z%!_%W-7XYtxJRdSj)Og)oCF(a^*rHgR4NL(FePDWN%5IbJ7 zWVO*r%fU?2W|1mUuqwE@CDfS)sBNL(K)M0)uc*)|auu*di)9RaXTnFzUAt7VBIyD{ zP7!UO#6*ZDh&Vb!crX=ry~4(B*WQztomQ$~U2$3VI;N(rV|k$(MtffO*t3bW-kPA! zdGjHgmQkoN8!=|K{^uI&N$Xl=O)gr?vf|sVsZwt=O-w^AS`@##kfN&(JY6wsIg#BG zA*svC$C{|fJ#18=|dL;`he%T8X#U8BAE2KDVOgX8?Yt5qX7oR*B{OGR6)nHX0s z5pTmtP2Au|)F67MUVtx42~#599P}ZDg7`Qy)K_L{1+Jp=bkN_JWR~cDBU$&8axmSE(}wMd;Y`` z=j}}9O#GidNe!q2ILC`+#m1eGupp0gUW3EX%{3PRCru!8)OmM2*M4pcy8m$7_}kxf z(V||N$n*7n7kQ@ePDBDDl%I|FZvs{jxq7vu$g;!Ji%-mO??hu1BrlpQHgx35zDjkg{NZMOwq>s$PBIvDgCo`7{MW<@vD?>Qjo^(&lX3`g zLtsmSUL4qUUD7g%JU&GfsDCzAKt*}?Mu&3J6M0hjD@tm;@w4gr2C@f!8_JTbaM`bHm318#YRq$B7^!| zDg-#p!y*?Xgub8MXkvnIA9gscA--mb>3V}~iY;;D`P{=nV-{ksAqn)^T^Xr{Gt3w( z%)rq4eG=6(twZj$3#sjmRog6LeZW|7Ve>)&@z1^S8(7M0taD}oTtDL7^DRv4Q3|0z z6cTvGK4csym}!V*QIVa~cToI}g7)iyV+O1+)gl%DV^6^Q`TEvW*JQ>GFJYB(hiMj+ zHWm*(-6T2`BOsVqtdJqW2vusZCoQuu8kirzB?oKJrftBHGb~+llKQ=a50a++e)+%m zmkEcTxs9mix^Ll}VBs}sPzZ<^92mtFcb1=oy6!o-V`G#tU);*oc%7uCYrr-!e4XM7 zbIPaN>ia!Yw9})bPI|8h?${sPpV;Gy+wM@W;{s&bM|4%psU|nN^LaWa*&6`9F(8bt z2t?<2J|pu#O=VbQXOwtY()q?n=)k7en>bTSBL}jagB6#Qpv^7r*J~i2Z?c^(W6lG7 zJ%UDD80RQ)<9gtBosdYgq7$1~)jervoG0|qsv6ZT+J4hXgIpG=>EG3L!=PWXg*^4j z694_(F*C)2>5s)oH?f8J|W9WJM zV5Li0vf7z+;>}E)1Vt5)XIvG`j{IdIbht^9ciil>gWSH4n4Y5`G#GxcBZe0?HN~P^ z7nB-o*x*s__^xm9t8iA?8n;$MU7LBoxEjp(7*e1Ub_TpByxP)d9)Td`2_#P;B~iLTh>!i~5eCDYeH>#g2ykZm7CfDlD74}$kL#s*#qLkYrX#aVLu6))XD zr84oU=1D>easU{*8btUG1n97KRd1}Z>81(dl_dYzN##`e=&xwSz^X2TaOE1;NY;5Ux ztUOF+Y>q+|bGTU(vrJrF)qsM6Vt^0$@pLhTF(IEQR5c!Vbn;hWnC^btU|W1N-dTz} zZi!7ZgD4WzOt(Oum=v66rQDBl-Q@q?>i?;I;#dK+lbNPt`1=7S#rs=N*I;*FAu#d0 z`_3iP`;@*^m8JnxByRV(i8noptjTDPgAHUT=AaC5CX2GbWwAtP zP?XWlloC*2;_i}hxCR$qcl}@g^$4-Mr+4{6U;hn4W}0uRc(xZIhB?Iv8^(zgaNsyF z=Lj6x_8YxN2~$Lo{1hr%tN_P&VR_&(X3# zwsFHw!Ogo}Eb7KZiKQs!Kmjtp#XtPa9vd*d0!E?FoG4^dy69x%-C_H{T4LQ7L7)U< zmXN&MTxR-ER_1PyBFggJ?)RZM@b{IEh(1W6Jq(e^pB5ryq7scusX_xqUM!Hlf9IPf zR$nwR!g3R*l@d_%OYicHd=5SSw>eeRY6ih%d;_XLm$@=5{~rlZdX@n%L1e$_>T0`- zyE>T(aUgOgmrHmM5q`U!&~7U+Q1@bP#yWO%dy)o?mE#Ao1hIY->m%ad5i;34;o&4u!>%)xGQV}La~Dp<&A8bVupM@f zDdq6F`{(+Yh$M&=k-^U9uPtZrg%DQ zpdyC3=?*z6Sh};;AxjKM44DSfWh@UKgbMxZaY0B{)6{{178#H7s3O)EDP=eVi^QD0 zQz>Oh;Gf|JD0)N;4uMb3^s5jwmiE2eTFjA*>-5*yg_v&k9LVc_2ya;9%eb#!yE*t= zMO_?`VmLTons`R}Dl*9?K*`SbBq89kXjsyrl$CzGDz=5NSWE$zrwtBd`5bol-2K;m zKOf_k>lNt}YGDhb@cdyxpT^RgY7Te9`6WRmW-w?DRJv!`+-k;~ttq`~`qV%jD~DIw z)GODJZ^e}o5pSNBRF^KzNaDr_pZBBW5|X5dXw*R{!Pp9+@T8FpeZLjXMZ{)L9e(i(T8ZKsIoc$N{%_Cqf@!;e_5Rk(h?`R_>`}wDNj0y6L1Tc~Ot1GD zH=kutWflN&<0!qz43J4^p;gKX(rvwL^Z=RYOuvDpn)rXBF=$lBs&G*`iuY-ugKK=* zaQmX4ekXAi)|VzV(&cJX33Elk3Y`{eXljxqNf~HhM(_RgX>dC}8O4y+ltX7thanCv z^e21~kwT-qpeUML3+b1y75%Du_0(ZnZ1uv45*I9Ime&a)tE}ve zep-#E6@oy8%>V>0&!Q=260g^EX0IVr(NK3pp=Dm{=wEj&ZNeR!UtJ$M+dNUMW&KZuD=nzscVlGrL`} z)urHBid9EoCNSM4gMOn>DV8#XOYi>7$w&V~6mIUWtIa1a1-cMuX>Tsxp3t(o1x)l~ zx4aK2gI{06P-7RUgsAZQ^}qwG3Xy z_7L!n{xfG)SAPSzWI~cOEL9!D$IS)88jppd{d~vfQJ!fK3xQU==w3{JdGVmi{t4gT zqL_VEup9&wT@qR3Rqm|49GRdmu&mI9@T;UDjqoYe-<&hAj*vM(1+bJY1J7(g>4FJy zpNhn{WHi+4d%;mqxe9YXL!IFOvQ;i{pPDWJZs8tUax&NZ(?7kw5Yr$tZMi7dM{8yM zj)ro%%PZR!oMo7&N6^|Bsw-E30ThcRm{gSxHAjZ*y!w`}9}E1xiO|GkvDbG%aGvqy zdj1C6T6OO*1=obeNGCBlm9cvhY6imq zu~J4V8-R0*Cz+Mmmem74z#FXChBPQQ+gpB?%FY>(tG#R?%Tlc90F&x&TM1d197++) zR)wJ%!4^!ncm@xAy1#zRur>Ya0dV&BEQcFOOP|l-&d&GKci;cIO_Q-gB;?ZIR~N&@ z2~Pcforn5tMEicSkG+1jW1$1M?uTKAkxavkt1W(y6=Z+^KhCZRw;$-?-h!FCgj>Wa z6(CW4>w^3faGVw-^v}9CM=@NgNT`1rrHp}W)Y$PEm_92_9k|}H?~pd$jNfB5#6P*_ zV(&wU;d#+(>QVw;yzC>}!WXJlia^z-z5eHbo3crNMA-aM4$<|7=Y@=c~ z-hf>xkOOC55#W-MuFORsK^;;1rb30$%5bS$dx0PV49&J^x%t!DT3L9aJGcDPYTcTY zT)GoeI`6rB=-1)`7)z+=`{06)ZRLuu(hGy zRqvzIbS5yqJL`jbLNLr=<^BHg>Gm)#WDWWONayP}J@JnJ^>SW=ith92`UrH|YJF>U z(#jn1`sj(eSBH>coT@nJpHMNy89~Z#G_|t8!nuVsO(24q6SWzAScK&VX!4bk> zDDAGUjSSwpDjBHn%AdgBCKaYfx(iFlO5C+0P4N775Ln8X7<%SLW}v1t1h>}+ ztaE5wy20%ped^Gzxr@1KNeF?0ie+XNQBpdl_!+U?rHyE3;9t}$c&Z?>#tpM8 z(temD_ZXsBb*26TTm{^Z7K@?vs=?RlonfF>rXkT8I{_-im;e88PnJ9p_4Z{-k2 zE@>Vc+dDj5B4l9~83LT~!j7t%QvA*jRKM&y{j3>v1qyY;`j=a?`N|{EfGI6NfTD!< za{K-bg(5{GBY2xEk}&QMfKhl4Ehz#-4a)S@1SVXIu6<*4JQz%X`=;7@GXCAoy3d6r zgd@+9^I~lH*GvqNjc_5c1``7qc_Pa4sgil(jCmfY;O!G&%*40pzBzeGs1%Wg=PJM( z+lr)AtMTFU+$Dt+CEU6NK7Y#cH$i=BdfGn|`|8j0_c!yr=Z_CZf2>li!Y1&Z1hlLb zStfCI+Lt4wkPc2(vW&yPzt)qo{DGP*UFGAR)jaq~`9)HPI0r|6l<6qDwJaj#M=Tm| zm#0b306I9C{HYR*`2wQx1?pL^s*~_5ck?H>(jZC;LI3OX`~K z9By%Uhs^C=(e&YHl*#E?e!i)YuCpwTWKrzkn_K&^c{34(j_xJC__vD>^5MpRRf)CC zxKDS+iKr*lomegDA~7gG)ZO_6Q;AuL@~G2~y($*_`u-|pF1HAqyutSWFp;B~Pv z;t&5=+@V0|WT3i~F-Qsyv8YidjXUyh0t48_|1`$Y{WX~Iz97tANl=)WIvD+6C5xuv z_`41U!R=x%2!3o@5PNP53si^%8z76K$Sz}OiZW(VV&oJfpIwwkv#r|C#4!dAB2)Z& z?oD^Ir*pGaK;J2(CCb-`ihx)zV_8gt4KnmsZfiJv0Ja)N=k0*~(Wfmenx|w+Lodjn z&*D#$D;dFXOyN25F!65wW5WGx%hNqCsU@P|+{m{puueP}YbCpEg%`;U)+Relq8wYl zTRHppqnOgq&rcwzfkTbFD3AT21w^+|G(d7!Xy5HOwP&Lq=JPGTu$;!yNr1)iz#*mAt&1dbT`!YfX*~saEv_k z#7bScC0$YJAX&IuXC9lrm|mFm$m!<2^<0Z(wa+^L;v^e7ZgWQjNLUmIwRnt11@e8z@g@h^OzqOaUDi%R4EQYx!)nEU2+GBuivs!qVh=MU?$)N=k zKX_*SCAlH>PsF6M&tq1m{H3T)(T$ii#HBW_js|Y)4tDibk>W9}g*109Dq|Y_-2y)u2xvjA_oyla)7tZC|D;{KxU_8o*p zvt8>sZ_j_T9QoOh?Uxc8Phl@v1g$FEEcu45NT$(gC9XH#w0mTo@t_1o%MGQwUc1NG z{sEpragQw2v{U9nvusRBe&rOj2Ao|UptkxgbkYL0UL+h3@eLdwwY-#ftl3Y{N_I?B zR#W2^^Lr#R|NSzH&wNb+lM>`wNe;21>FI5t6&HLdG2N*XOB59Kx@xB0t7`V$9@0Z(5 z2BB^RpO*MX^6;Y(mEZWbgYsK3suf-jMY#L&2*o5l&m7c{Dq(sk39O=`1RW|X^5j(A zTc4=yKdzyQgoK+Qp^)~{1WzSRt3Kmy$vW{LV%&MZVbiOoH<*6LMfaoQXE&YxCjwqv zR73Q;pxgrYmw;MX+<-;~&dtm#%`1#K7+1hYF5%*`{+a2KFq;vym#hnklgsX#ft>_vHs109d6(RqZdWn5wq#C*8t*)Zdi;C!b z+_<9(p^Fd*9qjW=kqv==NIFz=Qh`;B3Kr>k? zwKsJ{`yf5K@lfEuw2kF+NZH|$% zgg=#|>+-VZ^r?($Z=RJavOuycbWJ&)f9`REJA_ZW`u|BP)YxpxEPn^)4-;i>br5z( z*MwjLts(TC9SoUDm(OfssW2n<&tWJ{@Ybzl9j{gbp)Ar;c&dNUWi_eLncQso?#jOJ zc|F!L0NeY3@Bg?*N|uv_QT{Yu8R5cE?r9oY{o4{5aj)}Q3eGkJBZizbMcaBx%hoc7 z?T-W$TKI<^apUGU4q5R0`%b)uoQhiF44v8lZ8#3zKjWS~MM_@$^|>0Dw;0i;tj7N{~R!(DHKT&Xq@SW4*-3&)N$q^@`YMe{z~CFiWQkF19)q4&}sHj7cPNycGp1g0$X;*Ju`S+yn z3M~C_->h)5eUZ_YS&J1J7{(MaI5XaC5~Yd1(>~ijt!P+%^~Gu;sGl|8B3BL<;##ar z##){L3uI+|T>8|inHrSFYr+QTJU-l`%E>jI-KS|f7@Nn6gA+t>Y ztBMmkagS!G5=n>_S}0ZzQdre^lea2729BJ^8Zx@7)6Nx(F1j!-gX_mOh%Ws9MP5eq zBl-=VC?JyGc-jF#QbFk88N2BH+CPm&E9#&uu}66K=@voJ(9X21wX zDnpS{4s84b2llrt$8;ZXeZFq_vcEOm+q$=8T^StANfgnqmh7lYV01T;0}&t~KqA`p ze^c^P$wd~!0CSDn3>>lV0N6leDOeH*%9#f3)Y5~{LFCdKo**MQ>vkVi>c-chw8j%> z*qSA&&(P`mItKA#1_>&k6Y)bYVmT_8RU~`TRXJE-zyRWKFooRTpIS1vXqMxJ^JUb| zC^N@Y0&JwSxarj-olVyIzy?I{nnUA8aVMKG4wdy-N!WfWfS6Pxnv>?}KdLZ@Y1QI& zyN-4|(Q{?B=qcWLQUmUpPDkNdAdr-P%FoVIMc zA0F_U?~oWe?OGfW;8=6*$J=Fm7YIz(7+K&|=_DW|N3-E810S zdHNn>jaI5>7<$AKIXmP>@V$wXq*l7L4fJ1#Qo6J!a#b`D%~2wz)-{;?&_4!5I#^27 zGWZa>zYg>vqD|tO@eeIo&lSI;Mdj`7Ba-W~)#2Z=A=~s=U)W9B9PK$9t4X#3VjFF& z=L^rhL6_$Om}uYrs1X4*(^6or}^ zAHDgWu_6ZNKm%NOW1*p;A#)bomTKv$)rFeuj4Z};YXDH+l*vz^9C;iWTTx#El*t?4 zD{4-M&>J)gKySCClx@Y0o0ORQ-b1Obp}Xqt66MV&?L&z;iRt-Pn~DCA^h+^F7G^fr zsmjDptU!<~VRZ(l0}oI54)FxPMFy z%o7U_)dspwO8-HG*@q=67~t|#r9`u|h4+&@!HZG{%=m{h`*E{Z%_`oVZp1zQxH?~- zY`RB`z1|qBmq{jHoA$Z-B+T8y5lMuUhnBx?+5%Doy`F2ntAx&ln@#gg#(;tx%hJcs zPuB-8g4*5RF5Q~GeA{>iWsHK)?%1zC3iv0gyMUV)N70i6U~obtB+A~RL1N#^UHTkM z&LZ)@DozTRtSaYY8+Rt63YU6w;2boYc081|Q@X6#vY{yg=?hbJQWU(x&YC`#1c>5q z<${rAsw*qG0woVG&%%GrB@ZfgPQ|b9=WMugAC5_JPgvzz5lJLaY#rI)R7QH#nmVW$BAn8PhwpJ= zMyiT0P@yaoPea*g3#?NYY2gFq%;f-YLD^%4suepy#Co0&?!RLyG5W*6W=0D4zMoR{ z>3$QCmqLM^#nm3*!Xzm)lKo>SSl@tWp!G+4$UJIg9u961LB60Q(aePS5PaVC7=IO= zyp#pKOU*#vTz~S+Y7sX&K@3KaFUQQ;8O`hI!tAJeGf}D&ujA4alo>1uYB~U2QK{Hu zLk`;xHpRq(KY@>z+ye3U)mL9{9#qb1Zt_zGZfr-Jzy=n!DM;=uxoO%*l0mRV$;a%CEfX~MFtLfH_9oQ#qI@zD#G z1CuTMtTecDrW1qH;?G$&vokPzyq@QXMgDpYQ6!4NesWCm8dusB_NUHo5Q$Z&z{WRv zEZ?Qe#=DT_&+n}=h!yfTmF*chKF=lgG|Z$yR%O=Tf5F5!}=DL ziag)4g$Yh1F!TgcG>AtW(Xv4N80XsHAfLXCEz(%~Svj9uJlEx|v3^*)V^A3#9W+zw zzZ3xdGThvqmE*bh<0Syt+!^I&QvaKV?t6+nW`rcNtQm5t+ViQ?7mF%sO2~qziJ~B0 z>lCA({}P*}frL8ET*pcgvD}k?_jwE=XqbUT2nb6eQ4H^yD>t=@vhv3W!G>^MYcTer zZLH15;q|cOpi!kt95eYtl-u2%qgwLEWL>>0M#)^V%XUS%HSz-Jxw4t1zDgta1yHRD zKGN2-d$t~uERU4s%#60ZKi|-pHfdxr`T;$T4U2<)Ix@4gGz22;FA{Bs4dBa~&PcVF30F?=ez&=bo*E;_mj z4{*mBg%%*av3YMl%DChx~U?auuOOn*sm zS`NL_{V|HEsp(AzkJYlR@mZ73C{b82pOUQXq`K=j>UsI&W%HBMqOwl3eApsK_bHR@ z@Il;?;lo4!l_m_{O+@B;lx(c|xjOrLs?-RJ_=uEm$HuupajRsBAEiO1mxuSkR2EwZ zbKe6rGC8mz)>L_TZdHn+{%!kdBB;y@o2M9*W#rwLUC3*{Kp){KOcwCQ1c4D0DX3bUn$|$6S!AZ*+ ztfg&(9lf%&UJp6D8>6YIJQ+f6s^n7pVjflqH>zjGJ3i5v6Q?I2Ecw{6yKcJqe(CuM zm}Q>U584sJn00o$oAr4!pEAaL1(XLLY0Yg^Btvxre>rWN`^=f^)Y480SWzbwF{zd% z%9W;~SN)*!n}hxhLrljAAY1G%tkE*JIMC8uw3d!@VwJ-)%!g_JEzpj*HW_5Abo8!9 z=xgoiYa8u|&BV<=z1C=TqKvi@9i>vf+r(~kQYyqc7mj|rOl8Q6;ZmA&1@fk zW;9ugQi?iBQ)e`tgJfw^gCrqHywhpSq!W{qidCv%eW{LR0}Bg~m3BNaPbc;RbQNsYzvYnw=rN%M7-H1ZYm=VThC4W>^>`OBJa8Cf@2utKmuS zX{N&ygIwuZ<3=X+1HSs1#ZxbKJRkQvZ&z8zV^0rx;i7Hr?HW4QX;o8-bzCz=sJ3R% zH_y*?6y>$Na9QKXa$Ez^lW$+ZldvLo2kUfCEs(>!bTUPa0?c&O78g=_4{6xk>|}jj zR#qSq|C_OPe{nHM2Ahqct84Ozi^pr4S-?)&wY!&___rP#i@`C|GTDjvdUzaikE^C4 zs$|u!KLWH>6ARSpe5q8WsHw@(uA)jxBWbgKy}r=X^U72X40`4GJkIVw>$9xp8s4+2 z`v+Ht<7@aT1ss!u73U*fp2sra{{Eepdh?m;p&63XdR9%IHkIS?HUW6|(Bnn3kp?*k z$x|#vtAUG2WI?rrInDDx0Xi_PH+_GsRu1p)*H5I>K{it91XvvtXhJIl?Tq66SaQp{ z1K{LPIBq`=6aYFm5u<@s*nIdP`i5x{0NegDu7_IX_qf2nmGs>0c>FX$o2%i51N}Cc zNUlOgH%$y#b(n;)oFx%5GF8TwU?kqh5byPiEq^QWywmQ>R|P))n;ISr{!!9Bq`S** zFLFZ9;hgyKeVi=r{1e`0fV?|Coi+{$_-Wuv$+F0;CpREa9QoT`y4nNuFqZTz^St z`tkK#de!V95&qZKAv=MYxzg6Ifc1z`sd^yKD#ECA@-=y45c1jkxlT(%Aru7&oGy01qS`);X4A&c(p#>2 zM!^2j9NL8VTU-DUVBl`}C-0R--jW!gEAyZXLtF^%UX2!Em{}p+Ti^dZX8`i8EDoqNz3^=Mt?iCc!(GsZel)M^-u5 z=(y16%xVH(B76YT<$%|dQLns?~*g=4ID=g=cZTAaY;co(NT6*&ZX`6$^GIe_(AtVtKP zffgS`M8)4A3nGnwKi%?R^;tXhZi(;-4ndF!1xNW#9CdyK{TItx9Sw_J4vm`h$X$IG ze&A~(676S{zSsM#4p2(-R(I<`tZr$J?8@%a z2M$;wP1>XD=Ja|rZ>5~#8aSwW7OLUpCZu~t$Y^=(P~0JS3KnY6SThdyVS-J{1(AB~kg7&Ck% zgd2Wtmlch#(CDq(Gj9E=0Ap>ZYabSS$pcEIA&C^dUxaE;#uGf4PFLU5beYF8!_vM*ui=Q@L*;wyCY4xZ)vGBwaHv2|V*Rmz_ z9Vi6jfCCm=h@_v}c#AKsrmdyM+*G_xQK|WD#<;!hx2Azf#=G_K_I|hTLv6ug86~h! zCOEB?Gd(>Wn?i);tzQx*Gn1HkAq$d+KBBn|t3rE_O3fa=bRJEeY-oKZrnxOeMvGZa zDO!dvVy~5>Rp!=5+Fu5U^>0X!X_9l{G5m^8;vimr)CofTSZ)6_U;c3+{Bx<_X7PN7N{^R z8)4gRJ%6!p-cyN9^9(vO8s57zvHzP|?jWd{fh;PBoTxI)?S9LI90#e7)2skl_XBPUr{2Trci^Mgac!n}VbDYJY32Eg=BNgDa`#I#7+? zGdoz%j1}uD*4>6b@!ofHasWN;86lf1L9Co-p!1PuZ5zw9N%qc__*eAQl$`J3QqIw4 z1@O8OtEtw4+3AvIeiH3{@>s8){fXw0Dk`b*rRM@TkbXEwb(vQi@V-Ra9ZXmHipLoN z=aX3J`EXS#IJu)57IJ0rr#E?s$VtIxbz&8x2bLklS6&Yf4Ja$api5O}r5{_l zhpgGA-gq&bLZ1r4BsXCXp|^||ld}jU>>;nQ5r!LevBSRjGi;ai#XbdtUBN3my-K(C z(DYGSdb;6wGA%k;_D`cRb%jV)t-f_8zveQeaiqUvi-VR~MYX1f3gkn76N%@SgPY6Y z>~gcb<(XSQT{~2=j8$FYZ?qSV(JifUhyPw~SuX%Hv{ImNPfnb6~&V$t$%-=`WpD1B>0i7?2Xpa{KP z_YF$3{SBrZs1h6#sThurNchRlwbt%FNZl3YT^%%;VQaLwO;)E1Ce6L?G+C+FoX}|H zHnX%V3tLFcQx%}^Tt|N)|cI+*Xm4N9QX3SQEK)rVK*&$ zomE>lc01m7k_wtjy(g%2FD=TaB!$gUs;(>T2RgP!S~_v{M`@ntn5|)LTSO-03g`G! z=WtwLyJ`-U1i5gcmsb4K?K?%|l=dE;-}uvdkWi$Cst+AFb1Y5zh9b?)#0ZRz?6)Pi zU$U=Cx{q*T3K|69i?B%?-zuwL_GuzCx9K^>@T)B5(#z-0MQ>EL9ng)W;^tv%_)fe$ zX()41MLT>qxn#;3?6Y+9URR#m#-cxB?KJ9voXZEvDizq&n3UN#Ci)Hx2^z!zsb`Q& zXuJ$iUI>m&Rb&}mGzMC4UhxDc+Vm=HU{h$;^xnfg`1Zc0rSA0WJmJ@d@N|lN4jWfO z9^Nlf!e;ALA=5{F)EP_SRm>O}F9Pz=WVRDF>m`}*tUO^{yiw^?JIdgdFI1M!P%c16 za8}0lpU7G&0JbK^-FX*mP{-h* zCk8__A-{uVdBfKW^8mH8%CxaIQx>qs_%!TE5O3R**Vb!K>sYHfY^H|M`96UeoHl#R8C5ji2ku+Ux#{zQ^W1sHL(72+ z5<`mz^Z=NWd`FDT5%s9)rV|17^aal0O4&&WJmjP-Ci~SGqa#;t*>=4}zYy?YT0USR z9`Qxnohuz)`PD#0X*@LC$Un$q?e768HU2w{+cG_qfWp<87c1;X0shj(m-TS?Ve>T}d>t>L5=80Ch6qy@kD2Rd~ zaXcbG;(g|5lh6lCeu+RFLm9{vX3E9rV%?L`TniB;7$tJt53pR;XL@zBBmk;N@6At^ z70Di9)o-0n_C$a&$jVpr$F9cBM`A>5)S8Bx(o2`RnEZ3#pXLO|8ZUR8nk9W-%IFT0 z!e&w`W6-N&(yLIo_mMIPB@9aC5E?`o_ee_4;#xvg+@h<^GK?6<0Wh0_b*C0 zC!RBYC9-M`fA@k#J6ZLMlR;Bl<%R!D?U3;7P_19;pxG1Ry6;rvzr=W?bXj_hwo_A5 z3RmwT_e)7we{bp9Y9|j4ED*=03yX_-;sMD(d``2A(S_yOB(H8_*QZ%IApu!29r1@q zeugKJrcuTG4cmj|b$ztun`v+}I!nbIAceu0zZXU3*rCeOJ1u2 zd1sxSNMWeHn|}>2$1%UZpwWy~j29IMUYLoU_oB>`SNn?4iM*znFOuOW&Wq%ux~src z6OsIdOBZ;^DI^gXXY9Sld2)U{c{ldzD1S<=>y)p~!L7uXgb_F#hcAr5lL>%4vQ!Tg z#73i}rJE(L;Kgze6xg-8SzFq!5Q)QZSCT$bW!3byU=8?kI|;(8$(nKR;>|B`H-F+s zwndt5z&v319;1Rb({86yFfBCul6qV~vVWaX`82Q8pwVKQrOkik1=#5Fj}*D1=eqa0 ze3sK77Ox<5R5s@Ln-g51O#%=fHLTT!BsrZtFG*e_9bVVBsq?6*2Dg2@sO*pHNI8Ti zu>9ER{y;pxFDWB`v#g}_sP`JY)guIiZj%$8bd&fA8gwb>`p7_$C}`$knIJ(uSUYb` zx9OkojN;!~*HOK+#470ZzL=vQRU;yBi-5N0Qs4F_xbzj_!Oc)SU?3oIzmRd&!n1yL z!RvKLUOZdU`4cY(Di$><^40as`o$vb!xAk~W~TU6WG%n&Ed9{?p3cVEylDsF{Y%sn z!w}~xbQi_55#AF0Pb+!B(IaDH6H|ZQ$r?~eJ}9&cNI2+U)_9gfrj!|~&U|pBrO9(D zBHi50>5mpRc(s!~fD*mgi8r~LTFm~raa$vc`?bSKpY5z8c-?;G1v&Ny*V?_LUHr6F z3R@Z)6%}v0p7ya#?$5Vk6%@biImz;KqgYrNGn&q+&WUcEhaY>j$JRN(&~9q+>=!;j z7x2?1?!@v5_AMOEqHGJjR|%I#$9ZdFrVYIQETvqYu+mug0!PLssfRh$xi{%o>^lB! zr_*1kC3)dc%Gk&!0rV8yX!G2x2uhA(b0xF@(6ko2w@T*Q z(w+AQls*1CJ}*nG__hc{r=&x&hwbCr`Q9;ge9`xdhAIX|r~oVR-*x^us+LLV4N`Uo zmrX3r^iNKz0IRwLKfcB3g(;oJIao|4?OD}{)gLcv3?RV0mV-fzEQ`DxeaMAFsV9+Mn>!b;v$1 zo`Q6p*vG!1m6__Rh}kn##lJ zt6Ze7bK-g?ChC-(B-{B^D%^V zszGX@g)#JBHK5?-7p4CIo>NZLGVrXj9ai3A=t~yi9a-8SPq^`sY7gbcbkH+*^}zv3 z4{AKG{>)5(m-^uNj9RsG z^(%>XyWa@LXMP`LV-*Ca;@)*uRy>f5q;2&4MQNyI|D>rr`ePBGtPKFUc~dJZKQ+CN zSGxW(pPF#t5a}vls2^PQmOnTFjhGp5j#mvA=u!KcV>pg1kACjQjk%C6P{-$F!IHjK zBl%f9LVrUeH;&+&QoIW7)Qf)|L8YoJrFXr9Q=ENohf5UlEKx>6bs^{`(qy(CSYqzU z@=3B4MYRZ9g^nnFydcCI^pu3u;QU~267j^~PP1=TvDA6>h2P-F8y5oc2^|E?3SGO- z5VqjlyH658jS$%RNLx1)b(& zGf!K}QI@J~pYJt`_*`GRROLe}JWpU@-_7M(g%dB*_?{uY5}C=&aNbXFvNxJ}yV_vL zF>5Y-%)!@{H|@vlCtqUXQBni!3uaI)i@xtzOV6h+Y`i9azL@g)2+sd-64v&!5xm$J zlchwJa5S4N?4P`~WvOo{)VfVy)hO0jC&4E9UdO*>hPv_4k|%_%&Te&q)UmH~xT!|a zf*YrT%@Eo-YB5kpHgLtizQt3J!ed+a8NZ?TsnD@-UHJhR>5G4DQ!xgt811x6*T4`& z)Pn(VtrN>v-n#BnZg)^pw=aZ@e(ud65v=Jua@u6Ss#hiw-R>-*6erYnU3C{F+C?Sq zJUF_{Yk~L8!&i3eOSJ+kL9RicEtqQr#M(qH@AYFdIl{VS?WU04Z$aT?eqMcZ+2~t< zRloRo(JxY?Vg0^5FfcM8xrW)Vs$}q16seC$pXi@nb#SNBqHe1PS#kY=*>qyYc{xmR zyTcZz^guTTO%22Cw0ndOfj-%ZDT3)JX&1fvp;mw3Fkj{LLN+En1-~m6WVx5eRvw^5 zta4OnqW9*|Z?tPi6#YYx3#sU)pnwI(b?wMP!sVy+{a4COK;v8DxBJ#hR?uHMwKFJrF$=m78S?m1uZ2?hfZ9bNpd33KV16PpiE8>N4hErPEL&+8E$yA z%S&nci0GVf=0w}661(QhV;m*(v(bP0K}A!}4w3eM-%O^ynoNHK`DIuN5tiZ5m z0#-@}!rS!U%>505 zeLXQgI(>^_!E?XI#+HGcCLdPzXLfBO)5~U1*y@zRjt{(NqfqRlP#B@kq8f26;OEe? zhR~-(E#(6Vpm{sB5UmfAJD<1LlSPjmLKg#i#ji#OY-HC+(==G zwErj^lp9G=SyK$a3|AAuO~hqDO~7nwz-0Kk%Vc>=<-Gr(N*VZd-j?bn(~pVIE7PsU zN&HUyVnj~js`uV4SLn8yyeOcRfUqSiq46eJ9KO}Cclmv$7qdr=>w@@HY&&JxF$Cld z%pf!(>GMEBE()al2A$%3DR|ifbI$h9zECP4^ttU^`Ke&aQZI((_50Y^9Vp&XWw;9{ zBzeZ3OU!L;EIijy43d`B#JcYoV{zqcF5s4inC!i`n9f< zfcNLdDP=;1@KV@s3;a>)b3-aLU$Y^5rU|&VB+3_RasU@@kXp}@Pt$E+xaTsmM7cT+ zacGHAYbrxOmyfj|Vv3nZbam;;Fp6noL>cD47m9fa-vW{) z-d$X4eC>yr2N;WrdhY*HWf})&XZut6?Ns&8;vd#$weqor`%dxQQGMfwUi z+ERo1AA1M+0>TPbT+kxYu$a#Zc4H~XW+D02W&AbHU$Wo?E*vwEBeA)T&AYx zmGRZ@w$p1{G_;%YBRhYBh++x`He{hA_?ks1c3~o86k|2o-XV_rc}l>wZP3kNj%GhC zqsW=h=Rf5uih-1Ui0IP+>1(UD4>oI{1oh`y4bh5=$}Lh?5n6p8rfoaAW2sl|23z1Rk9?eXy}xZWUzeMBd0z~L_hZY2+t{NToqYAr#4!OEXHTmR+G1cg zpXxH^IS)Ox-3Cpe3h@H6Q4&R5!WdtKVITSMsIRK8x8nXtG6*FO-rbu*;g}t&vZ7AN5R^X2S?@jkpNLy% z)@_544EwUxdiwGMrUBtuj&A}XH!!X>1Sg< zKhepvv#ku+!{0x$nWC4v!waGi=#@ieMO8@05MXXS-;#2-OaJ+X=jMhvG?o7oMp9i1 zah><2^H^=)^6y)nDpJg#0&Ff;^o|566JJ`b3x?73J(enp?n&qeKK{o2xl{`?9%Rvn z*Fk6u5!LHpx8e`|TmSZKI?vM2fbX7(ifyrqla%{;$V!Hz$xEJ!j-sBXyq=SmJW6&0 z8vwjwe_w`%IzC=T;wmIStlr5yPy+iw?CT$?&NZbg!D`FeVX`*;-}%iWc87Y{fK50z z_;mm@!qDVRB(5eXi3~!T#_OQ;)2rety>qOofaXi`4UQtow?A0Vzv5KSMAuY-mFB;V z6`{{qsTwszC23(lx9N4V*(^7@R(NKre*;9uzXpdyjD2IfiNGg%|4-$;ZY*lSVyLQD zS%~;6&AvS5A?db|`9%%k;f{ZG1a~5<>`0Pa*7*j5VoJ zt!Q}QSF)e~cXAAVqbhUg7oBA~xH*Zh)E*sBIp!lJAqz6(#uIRt9!7CA93ZlD&ZKx( zza9UMzSmY9Jrl%V!VMTKe>6xLf2mER%SxE1^dW~~IE*RYvEcWS{_WYVhkRiOi%EbU zA0FT6g1e&S00Wvt1pQ1HxC9M%^(cXAWk9I*9%)t`zS(D)f&@~Mt6AwN?RBOoJPE=V z#@D7zPeb9+`?Uh6hCsmTcAn=Kl|`i)g|6QkZKtC|#C) zEkt(TDBH-5hVYKaLzC$Cy~dv^OWv5#47-`*)M%=dlAkw2ZLKvBiP1bRTmPsL+VD}+yiq{5R#YyF>8$!1Erl`YzW$1&H*r3GS?=%bYE_`^jNYAb*y>XH<;Ti+Jl z^#R3^s9E{CVgMiTOigL^D@>Q86+9jG^jPz@voU{o>vK1d>UY#)bHI6b1+iUjbV#dX zv!h?pEY?Dn;$TjYpR(o8W_lR|u9|0SJ6eZJ=rf+xZ@LQW>+2(1?k(0;mYBEI0=M;0 znRdipyW7_J`xECjud~X#ju~D@H!nRK(KNy5w%%8<-I)P; zhXGo+N*JS7l9K&yaF*{&K1^SHWi=!wdB$NwF*IoQ^HcC_8lo_Q*pm^r?sPH!Ui->R zYm75J0PUSY@#x;6gV}l$TdbH`wr=V+{}r3wsROD|3T8)SW^8HW4lKjzVJGxH2}@sz zhq9sVfjVgauUaYu(&xL0`Omh?|Ki2gyvEL#WRA3BNk%vgi}FATnW{&2wO#a%rF(aE zc>{BlMO-;}KxL6nMHu(&j$&$%XzvKmmUK}HSeE$O1ZJm(^Z>i$XN%3pvtCm$D+(ck zbTtKdWro+mMmb@?suYTI?s_?fHI{GCJH-iVL(I%8v6AUxpNrdz2K}>vO7K1fMHc02 z)~S-yFZ@*Z3sk9Qyw?0;*QYin+Bjc^(M(!*1VIl`4w5a5Y4^Tb#Vl`C+<40k>tpzV z3>xb6^&s`*(fUIy|l8~SHHc}Ed<{!k!WKBci6i#bC~&hU)e zrQpkiVxEXgNvr#o3E*+svs(`g?}hyZPG;&!jJ#m2o*YRA*q;?X5amrud^P<@-Tz+g z=lLr>OVh%_!9lsRddRK&wHMt@bK$-081+fhOy^2^xUh12+Sm4&-#cDSZ|opQoJN6NG14d(&efD*wf&BVD1exZ5re4U4~;v3T*LR! z4i41-oA4}J)T_f`XXrA!yT^k6!RpJ{1CCWVCdNG5E-jVO{7j-7=Ix@c=v3zde+D1F zh4Jw_E>WG;>l3*cTFAzEiXH<)WWH@OfWJcC@fI?SRH^Lp{?)zMpT}QbUMT2`sqE zx};>+UENsU@irRcN6f&fZsXP?m`^^^-2~a=1z%PXEvJWeIGTU}>zAcH2VT@$eoc)5 z-Iy~qwcKLj-N^8ktG}!5>O1(C3g87^ox9ARnRIUPBuWt4u~n^vnAswf+H0x%VrBN{ zXjN@_(xP@LW~ukxhFo6^t;O_`SU_J131asQ!C%Hl%%}Mf^=J__@St$Dij$Hrk}u6A z8XuQk-J$pW8p^`|5?2yXM`CF0*eh^x8dwF&Z@iGODK@4h~hC0K{Pju-FGa>D2> zwD(xk_4B#2E|>JnlTFi~-81%b>NjY=FmUx+_K&YMT^6Yo!=7o!D$ryR1J14Q8pG(G zNL~^`l7Y*V)^*Q18@5RSu3e8Znllj{sP4R_v5mt|3t;uaeX_-dH>Hl?ZvN%rKFNJb zcra4Q2MOOyJP_cS3bb=YD zCb*5aXYBAL`zR7XVhRgpF@}HmQF-z!Qwc|JYLBgc^m{+Q%q`1U z|FPDUFuibS-|cj;=Eq2@DZpaU(G z^=!e(cGshjVFF#R8bY@m9a4(L!^cz7ZBMkh!DjkJsZq>2 z@1$7Z2KL`M^1WhyoJd)zfbSzrk#IY?O-_7(toAhQfA+TmZqRo=36+ zrm-_A*M%iCCJGh!=u=!Jrg>U^>aUwAp{OFH79t^0$aQ`Q?$)xHZ`<4&@+|XMaM(?E zH}JJw&MWiDFRZrrQ)-*=#9OJWQzh4zMm{lJ@GMjs8`n(9h4G#XG}mmB0Uz!Nwhisr z*7?3l7BJ`fn`9js2Ur=t0Ci0?&Kbt#HK5A58Il$J?IZF&<`S!1%&UC^&8XjE)-j{? ztr^I?*Rrj3m%;hxs#ac=u%JI+RfTq6ig#W=F+Kg>z#ztOtk+}z%`5-)xfLw>1o@7A z`;b3>gq71%%{I>Q&UzOeHH{jKf-$r5?C0j1Q6Nvp&L60pt!r)U3An)V>-6hgZ~BVIMt zp3^LK7w2)6Y|7BFs_k=|50+NR90{Cox{N6B&{NNt*XXYyvkkKy39IPC|R6(WMgVFCr<_m0Ya1(?qBleCU>wM04sVIWey6yD7z? zXuO+mp+C|3B2cV~B7EwJj~|wrYReRm`|Kv)n;&yli{X$ZeY4U9-fV9w-QtAQ2iJ-N3>e#K&79 zNqsV`wN_{&q8QR?8CjPuZ7`N4ysao`b?_8g*~c4`IU_%6lRKoZW_%@RYk%AN6;wdU zqBn+<&_SRoZWI3J7dcf}zn7gdWbkxXhveU$i;&CEc9v`;wd4+QsO9QGV}TNB$!vx4 z8zn!oSK+I=cmN~n$X~9M4`@L#o@t*J#U1~qbXSoyLzsC*w9Vi%K?aURFx#woFZ2;1 zIY@g#m$7>m@u>`Y$Js%9VvULkp`2SD{;y$)#^wCMSncupl2DINTsoa%KB#W)X7t!I z#h+8XTa`bXkgYH&>VQLt3R2C5+lzu-zDQ7K5prt6L4dw15+78Mru}X#1TE*QUl=n! zNx{-YY$e%e^Mu|Vquu9|o2y5kSph?HkRdbr3~TU3z+5`@7kAXwAOm2=1>;o;-e#Qu zCj548X<8|5do_$c=j<#!J=4tHF~+R)L*bSNu5{vqpP2zA)Mc=dgWV_*naQACTl*(* z_$fvAHz0-LGE*)w)DFVQLn6}<4e_sv?V~ITbQ@;LO`=A;2I0{6Y+`hr2g+I4>0z^> zSK5?excK$PHf`CN!t8~Qw^-RX}vDZjqf>|G67tyt-0rTC#dnp`X*k8)Ll>RSIxwpVSG9h zH;}x8otLxmyUAO!^xr|!W6WgvGpnWd$#}FHkpn zv@LoxiIWdhR`ak+&qc_W_WF7zjrR;UA@2*ZcUb-)C9cPw?LWJa8=S2U>#DCy@1J)4 z6H~EWz_Yzw%4MSxNmHe2R-mpc6$`1A+&XzdHfLQFN;N>a}xTeW^eev`6iJf8?C zIQvH^!cuiQY&c9TsMok&usttSQd)(MAWOVGoAzJpU?lkb{J}>@Kg*s9S+|pdEWa^C z(NEOTfXcHisLnpSC{~hJWsLKWWe9Li!j@Vsz%F-;i$eidZNv?78(K7tkuqu5{^;7%B|Rmd&*2ArGbFV4muQfmD4PX85mP6byjaf zvir#+yPdOC()0@QCgP14yoy51uVUkAG8uF1r!E7@?G=3cm6Es_^SSc#Ov_N;&=tMw zejgMq+pLUgOpjJ7JoT2qU6n%GC&S5rvFL#kbwd%v-!&5AcP2qKGITr_*KY zN?>yjs6h;UrnqppIQRmvT)lLs6X0))W8o^|=Pi?-9yUFFgo9cSZ`zDm4mNYtGZ5uaZc2 z82h9P^_Oh{`b>V9OBDC~+=@&kGrHQ6A@16YJdsD@T|u=bz8i2>``wJ+EDtHw=#*$S z7Hv#d;eCICg9W)#mg8?oCs#kZLHiAXlp=}g#B-{j7FnOj4w`iJ2wB&&?XjX>UZQom zVrX&1M;6u0ac2le=0(ZGTTT9~9JD&v`D_~lOq9n#{*w|r7<*)44u%=}-P`-+%*a%5}9 ze8W$k`&ILDoe2j+$uCVwwpmFhOeyP^TE~Wa&uR|8a(dCkU($*|hn^S*xh)&-#cG>l zgF@yqPvO<0XJ{+(a3{GSZaMy1_EIyCe0tGACkwi(0f1zF^`)b5&#v8_0ijv!n=b2k5M?V70{FJ0RH)*%3kq1s$&(^dMo zSTF&?%4h7J+!zIFI2J7?g=-0DqwQ(*PCdM^QNFTRJbm#oRoCkIh>en#!F8RIxlPne zG9QQqJPxRRrI9i33iqe}LrtZx?W;9NN2Y;4-F8bycCmG`P{pz%6MdNgV){y?BLNZ! zeVd?-%8sXOKk)k9_(sEa-cH2w7lsR4crM3n@vEk0;yhIFF1qiN2l()cD>qKdFmF8iuC zHb|&NQ1hYImR1hb{T9DqS&u0$`Xw%Vy z9LiLm;!O=p(d{6T6=I7ULv4+H^o|Xl{WSh~9sej3oBSKH7kbYXav##EEL8if!=u%+ zc+lmUVH0_~x<&g7C;l^kCU0IimYU}vZSPH%HYEd&?6rQ)?(iGiXjk1_fqbBVLMEI+ zJyq9cEwnnc@0U`Pg;`Zk!_bOesNn~-0bO$%GHB(1NNT#>YNPg`TggsIj+NnJs)s$l zm7SL2?d^1uSGP_9Q8*{VU29MPso>YIeHg@D=jJ+S8kky&Dp3a}`XG@7Es-17ksV%% z?)(4-hUd_ONzG!?cLm%Z)+VOqT5zo_?{sg$_AJCr1|;noAOfoxLMI*vj+iuq7vITy3;s)CMrKG7+7`B z`1e;`YUpy-$hBfA^iBDC>KHuPv(u$(8lwxk?Wm`l#jdAW^>}T$r+xxZwL#xPWU^g= z^$TqUvicp3?iyO+**EVIL{35&ot*3n&HJLJS2ykIak zTDyPqmFO7=>ZPu{WvIJ0 z_<=3aDw)~c_(~YJsXc(5o%{ml2{@ecwn0zd)Xv!YjiGv>$5*e8D z<=E48qcDI9Cvu3?u`K8(P=2_+m79+J-g|6iv=LvW=eZ_`&$x0c*O2=4?bf@|-_uFj zTn-nLHpb<)|T4vj#-@Wxz z&!X~4i%ao?+EajyFfh7Y2Qg176>i4}LY`Xj#8ql8JU+!w*foE32u2iX7nvJa{;f?Q z`@pc>s4Wq-W=NFMLf7Xb8FBWGd^_&g3OgrxfP9TyvAg{qCuHV#4nF^55^7ha$9%2( zV6DesrRHEA@`dK$M3KFXmRxZFf5>TVm+Vs(%^n#6;HC|mp23K|2R)MhJ5RFj8#^4$ zR=u((iW*=Ci%JpiN|n}MiI}bKyuG30I*vlZoI77U5{h)Taf0)*BJ^Rv^Mn?Jk4Yb& zc4eXwhn!d6jL9BuYoWIuMltr!sfqD=u_-=n1#nq3m&OtLv%>1w&c3bHzS6%Aoi+_6 zVUn%;>bwz&7-zp$&us3%FYV_jA1c1DAn~2E-XKF)Gb3alNusD49{LYAAJis8BXWP* z*)8EQQ1yyX^)gWPF;L0uSlIKJ+Vi;Br;n5Ole2-N1mxJ09y(B80Xe=}-}%m-381%c zj<#~zXc#szk1bQ{D53TFs|Rpj6pFh3+BMGCqKH>g8Q3OfFYfw1>X=u>c3e93VCxeU zT>!2DN|a@MA7teI z@dUrqV`9Uv;}%L(SGHem=xf+{=B7-YpM)tY&?oRKnj3c-BUiKJ#e}?!{!{B*)Y3_X zkXZG$(6`K}xthNwK=EvwiRZ`qbw&Nt1Uy^R2_3)aoqy^Yj?x2Yc@n<7t;)i~MchTJ zCrKCz8o<)#qP$j0cs2aylO0MQ8?ODIst#?N5|cs;Ew<_g*#7g+ieS3Yx9k#!jVyY@ zX`JQL_nu`Dzifm&%@SH-L!ZYb;q^35Z3eABZxh6avSuOk63f;>4J}f{xo9$GV9k5G zQmzFi3)479+diPcJj3*-1zsIWr1^pAFk7ZOsq(d4?#n{1q7C7$4f9;71VggyT}G~2 z=PI8kx7VKvUlb%_P!!Yuo)WY=nV9O1?41Zsj!sB!pr6A?U%vCq8uwy{q(h&hOOMfB zG;OG}AJ%WeW1bg94j1dL;siVS@E%=|+A2!FFrP;hT!jPnc>cR)w084g`4uFXor({X z>ET+Y@-#7>Eurg|>P`*GkoA{|9gm&6&;QQ-H6V_8ftWn$%iqM6(ICRIE6qmA0@3gC zDutEHEBHf6?er2pWaK}qZrO3jU2$#IEFG(Tu$~Ju{Pj6E>E6HbT5P&xQ?mK#7o~MS z?zp+HNIxD}!7buo!~I&YA;}`%J*C6>(J^N%K+4vet-1?Zb`^hk$~C7OV6$|N!NRlk zvYv{$g-w!n%>r(POrC7&urk$dIQ)R?FNKXnr?k~fhxncnZ{xifF2wZ*+PLh^C2^3c z@6SNJ7gV-JWm$(7+nMWwI4qloDnnyLNaX%`FBAy8>j13a`377m!TZJC2Rpk3RGoo%ccd-uhZ5j9mbs#bC($K zeOWq$O20m4D={&Iway+EwjZ?d9Y0Zr^QeUy>=A) z?~nEXGW#pQPhsXP&o{MHbv`*l|#ZKkt=Ly6HnH@;_&X)vYQ!SnmB!N zO#A;!pUpSkIXD6|{H(TRVDtx!*C;DRqpklrWk`OV+PhJ2Z%+(na_YCKzMx_DpT_+9 z_=xoJC&dWM<||P8T{v!Hkl0=Nv{3~4vF{V$e;l0+oAqm4^1H>t;^Yj{o6-8jp#1;q z&-HV@&r@O@yYZ@Q^7Xa0a{^d(Oy7pHLm;|?WRmcCGB|S^%{97e%QM19=`qozBH5x~ z!EqHc%Fgb7ao(~*R^hUzP3!kBi;x^F;rvukM`t&h6&&S%x0Xu~1RU+{?7=IMn7wSK zCJb-+$63Som_bHwbl5=h#1-C!t-MLlhq=Uq#d2F17Lu)Nn~JGHoD-sLdsvh0&qvlE zxRJ)?f_+Q4EvV#teKjE74*C`Dl|4H6KL~YV>&GPZU1;6m(ziM`Mb2;K^x?r5Oz-4wx?8oVgL~t<3t>u zEmile8WU_5+{D*dyj8djoq3$0g^fSD!}YiPfv9R;51a8i)7Wwny(sGuwqOs;(OXCEv(7`uJUlMa)%Av z1An2S$X=NHeh8vKqSF~CAGDi1(k5Rl@8!KiE0c>RNFB}g^*!u7=HWE*I40E2SxCM+;}zGcN-4r z{1-+4_8mQJak{KcVN0I!ws$?;7eDl8-ecX=a|T8;dP*kY{SF6b`uY;436!kHh#sQm z20q|B-Key?Dq#Q}_M!F+)xKkgcW+IX5ALo7onGTfe}1uY)fT{i^iVdMp2BvLhfk@6 z%X~9RF4=`FbEfLnb+pN=qQXU5>ui4knCpAoT@tokSqZe_#Z=atiytx0I4pT1?)Q93 zmMc(J`Zs3PANM~2nn|vqZ|uaa73?k)?t^SChM!9k2E=CmD$kE}3S1BHp2vgIiH#gu zWuoP(>VHv3a-7Sl>t2cdyo4j*1=L^W)cI+j3uX_r+qbvGwPzI<zC2t}H zZ#BgL!o2BL+`rD#sr-EPHDUu=$xlBasr?SRMtyJEpl`Q_CM_-Pf8_Nbi>!>Y1;4xY zYfFOM{-9eKnL`&mT0r8Xb4mJol7%o|#Jp;|JYN55`rc265a(ji=_dB5iJ{2cNTAtq zsfJf)t|N79zbojwB13oi-Kf#u6UO5UjW1IGi-4NaJAQeoUv%$?q>0XMG%~0&wC}nN z;A|9_Vn}?Z@#!d&3|hlcN(kvz+VP*u(Xt_9@xQR5VFs42d5{SFSSXZs`>prr*Y#VhnV#{Ly`G2nPD=V->*UdDa5B|$g|Ff zT8B^f`Dvp^B{vC<&n>)(yRtA0V3at{YTvkexQ3==WOVkpJiA--<7s$0mr4;*#L* zC2ZRhovXDYGbLXWI@BtU^D(+CTX&KC{9d8kr1cp#QGaMKf;OA!1G9{dtmuvZVUfnXai?i{pQ)N%!M3pzW8+RK=Bup`BU?j{hpD5S$yY zP#V6^)_$QY3JFBGWSWqr*@3-{ywCN;xDNf+smgEd2FP%h;Gu#8PKA$`Y{;iSI3^O1 zG!#|&le^$m^nZ$LfFp8+5|rA|L1>&5yh6jCOH`FAc8? zn2Cs(lp19@UOjRVx;FUazuU@hBP9Hls*Pb&rb@5vXUdE-E zFeki#I`okP-pv2ay-hPMl5(tLGx|-VdysHqC{xOGs_L8lPpQJ*w*@s@dxVmG>&=ii z5idV?WGZ}F5;V!y-gU{NEal(a#@j@OiPW7gV$quoZg^Bbnk&qcueS^F4 z=Jqtn+vSH|Ldk1mYX=*-G=N`zCj{li1)PZ_X3s3@on5qr9?5BAvC$h~*s@yoXld%c zxPAePG}Q~YOeKDs2puIsK79+^({x%`rPrTl@u82nj8FBTgw5h8N_|z|Xz}YMRCzJ+9v=wo$WzX}OPm92` z%M#ykp)W>k>X8Op!ndw)!PY~5f0*b4u_FU68v!<;R?zzv`@Pygv9XJ2$bWmKDg`ga z-qL$pwcjt$v!8j%n}BW9NpiLyOVW*KvF_WtdBBQotvq%AKGOANRJqEVZhw8Jr|IJb zb6cvey|VIjgq{AR{`{YM6f%R$_VFl@*D8X1o?CzI{xY3UNYb+7M2f}vE#UYw$JjxC#qqK=Kb?+OtM+$LP@r&tj2 zYqz6C(T?LZ=;eo#Jv#Egbr#)zMlQ1l@72Q9BV=h|qmRd4LyR;@ zKk`Z~RHu(IyF8TaDb(mz=rX46FQL#MMaue)cUI~e&6x&k*2Co!@(+NJZTDI9le~9$ zT7QC`Rp;Z|pcpi21H0J80$*=Eb%I~O0M=^e?e^u*AYP-dLID$xg zt1AhChnaTV*4kaS9o^Jjl^ZwTraqA$T>856UV!0#sAABB_U@dR5ip1SFeOm>;2)Ts z_GDRsBQ>N}7Vd4#eaHFF`$IXNKz-3c*LDQl9V5`f zfGe+uf1KE85IXN!FJv*EMW5@+{OhUqz#oM>y*u}7OsKinWe?}2OP*(AklnqV+h{uu z{9L&0;OwB_Vh}uf)sf2%zs7VVJs3<*i*Y7A>j420yOoeDCld4rp+b(rAYK?v`fsD=NNu;UKd zS*O#_W32C^4dy%)Px${6Jks2A#Rfq0_MwD#Tb#pBUm>Rr-}@WML%0%6icHT!4*h?h zI(#oN@zaZV-<((RfjJaFhu!EIR_uWC<2R7`3Q6(y07O$XFYND}Hrku3`W2 zf2ofk|Hc7iDt+1T`FY7c-v8dRKR-A^{GoD{ZH)P{*VIrZU8$M)O7?%_oz98=2@#Zm z*Bc1R)>Y2}gnj=b1m*YxL2w-yyeJUk0DwgYEgm6wY_dQ8N95mddQ}v8=AY`;x#Rjd zwS85;sUF=M`m$<6a8zS9p)SzU@F=7T2ZhVJ#}9h=JKCm1_ve9Q89(mDdV7C0x(EG= zfZ-3qyN}bk1YmTKef+^EYK4MT5k&BduHtfElKgl5Aez!!^eALiq@de^$d@nND*s!f zAr=Z379NU0a9Z&6TPxpBbmQrv-5~5>7FD^UG`a4Trz@r=gwEvNBn5;0{|iGnpm$JL z(0B(>-qxY+1=Zm$mH*YNsOW;;2Kh~tL(r6SvyRnPhF>Ri+T7?qUN`hcO`w7xqm}6n z)`?+uASey9nN`@_Q?^Mf*ekd5XuV@QSh_>w^yI$)NJ|4s1r;(v!QOGex#~BNmlV)J zm}h#-y~5fd2~sg!Ti1IlDyMNCMg8(oeBVJ0Khf;b5V*(e9r|%BE7Kcse8ez(f8Jxg z73jyJ&t&>-(kKtK-o(d#&ybND@+CHyBv9>3Iw)Ta-|qzcH-{rrk_L)t)fY*CZ+KE~_T05-1Gn+nY_=)R((*You zM`jugCIa=^FOFfZnBThV`#Jrc-HOI*G>O3P=Enn@RUcU*sDk=8o&Vz?J{>3+I06Ok zQ%h2zA)?LWHp}x?6+XQ>vP(6u7}DstLUjUAV)>IpJFFUx-%mVh7}2Z~XsP;P#WHRe zCVz?2j&gTXwKvLt{?|WFA{-vXi3*eDvEERZwxyCgyRwoi%J^@PpwZ)?UkW@>SO<Z{|L`oI6j5D6&@ zkPuKxY2K8Qf=DUI=mueQh=hQ`9TG|_jg+7h0Y{JS6p;|5kCcvy3t!z`L-RZmnci3!s8JctZ3y##2Gg0~p`0s53Gn$Oc4-nBHMY=M@NhX2w8kPLigGAt&_TUj zz<>v)yv#4Fu{o>7lkBBM$ZXZ+npnZ=tuoT<(J{h+05u9N!rG%|O#q9j@|-yG9Gk<} zMcOO2;WfW{2jre;EMM68(0)#}%;R(BFhDp~t1DXK!8`9*7q=fuJ(SQo_O+Pco0`%r zjQSrNQA?i@7_D+?z=M`>xM?mOOt>FpZQ0^6dtp#>2=J8ZQD#yt_nBUDqTC`=WH4C7 zo}ZX62jp-=>4?ULQnPbIH$gsR~_-9ugSZA=qIO|UB6{2>QAnjj2)F+ ztmWCe=#Z+AeG5FCCJ7C$x9>^pDDH*SIG(jiC!D%7VIx7Rx9Z6-t_%B8mrIrYYJ^%P zZN*Eq7$wly%Ji&p%OpOILWQtng?WmiH&RtK&ZP$q;VB?A#@Ua=U_c-F1p66?w;qwf zMag+K|EV_^?nT(I)&xREc|Hf*B`Ah@UTBK6M?B^x1_-@9M~C7f5&;j?hLnowj*dYB znBdhy??Q%G$Lx5X{5XsLvRc!2eTzITn2FT}pA!3FBN!A}l?DNDPMGynQAi`tI-x14 zoTu+Qis!mi#uwde4}i*Mk7s?GDI{I;onc8^lLTFf^S)Xjz2M(3p1GuFwrYUXfO6tL za2kpsBkX`+&u{f+#f{JT#g?HKTIehnrhReF#qKdtnuBK#ZyS?N(f?&?Iu`o?1f)To zP)`yNIU6yNgejVtbb2Nl&B0}ITR1ZFBv^PC@Tpn|n}ur>U;e(G3=?)1n|6!2lR(=g z8^rNeiFptdzVAP|?|={Sj#&Yc5OYcdc*vElXgRbB+?9)9E}B?#f|cGt&9N(@xq;<1N!Lpxl>}#nWP~Jw_hYYZi_g;6+JpqMwp*10&Ph;| z)TcqS5ST!U5e2i#&5JSIadbBC7Fg_B(rUyRtDq$p9&rZm@2psPt!yr>a}g$Zf=*qA zHUvpTrAk1y_&3d8A_b5qh>Rqdj>5h(idiJFM9NGsY19e%0BP6?zvPuxx%M_>91Jq? z#nE+jba-V(Jg9i?9J5L`2{iAFU)99~b-RzbRgiQq%IAzyV&0e}Euy{<`JdO_q={X2 zx^8+}?ryZf(HY^RcWWyXX7hbmPnZfrwK+u#_Ia->hqiV^jCXYCJ!V($DAN>8y`a*~ z;*FQN`D%Xl@5^bwz9*v%pxiux9bc;UoM8EBOM>oqsR?F^z>oP`ZN0T`a-e?BC}VPy zlyDeLZ~5S4Te)!MsL7xN(oPja2+9rWFT6H`rWg=7j`*v-t`#O(9X z^6XNm3V^6ku~9%v(Vi%?g^DxrfeT^P*wvj-k$H<{3j!Anh$kamEEMv-bQ_*@vJDrK zn?+x*>GziGB3>e=AUzhL%e=wcQTC<3&&WRjAe-19rQ$fe-W|dbS$ZA_S1{@|@al$1B}?HMUtDXMqgLBF{^`MUbjH3!(h8 zqIBFtS@b|T7oFVN`hX@}ZpMx3yp^w;^HowV8ue!fAa?Lu9Y<6*EZH6# zlJsD4BIM}Dg6?t>tez_PD!V@=Leno+#fQwe1WZh$|cF;9%a<{(QsS;o0M7j zw|zh_sj}*kUgbK-%*@*L19R)OJI^F|dM6sc1f6aHvt-Fzd6eFLeQx8WAt@^(HOCG&H?Y`# z7N=T^fTYRue-|t4h|K%vFq@nDoKtRfNqcgon42(x`1|{J+0$b%M^(t~hFks%4obK$ zCwC*>F7L&$L&9lDSr`cy=UEvL@rq@ylwJRR*gvlDVyEo2+Q8?t6$Xp?B^T`M2%{on zO?O9G`BS8UE+6@mj;#Hsqdx2z~ipKV8LBZcK7erQxtnQ^oDB*eO0Y{1l$U*1pgHLxKwhp?Lgs> zU7eo8Sp{Z2onhLS<5X^pjm4z=m++|u1ot0)A9*gGjp(|32k

_^*Op=ehLem&S7wf^3n*plF6ce$4$fNAqRcjze3la?yN zeG++NPLMy7tdCDlrM_eJ7=lt6Pv>Pv>vLZ3z7`v_6oT@%+*ROwhHuj>H za367SaG*3(8L;P=J=utFHY^%>H8e#e&1OBDgQ6X~G?LkL6R4)UR`3wJInh z@@wfa+KStAb?Hkv{I)DtBFJo6^0jw(M_OTJVd6U~R8n0+IuElNq%%5`RY3ht<+Vwn zJW^lU_EyK}*vVpU;aN;f%=e6}^ocJ?Q4;CD>>##`KEOu6R&6!87x6wgd*N{NFWw00 ziww48S37Qeb=Y(-D$k;SPv<+Pbgt}DxH81uR8vhXuIzi-czNVP4TJv)%|>@1Q2&pW z8i?h7KBrnBLpG*r;_ZE@%Kd6YtBR5iSQh-yU%+ki{SN#0$Mjd#4SpK7Fm_7|T(VPM z|KdDR?hXu!WT)=$6dAc16peHuYE-P-B|nV`CZDHqsl4bewlotm0H-SVsgV?`%*EQK zFH^i}nQ1k?etrk_;AFEi|EYt`9H{^DYJRgF_}x@}U0tx}UW%|a)ZgWB>*YXSA2B~W zI~y}y>a}niqN{}a^HS%Djw035BBN$2lmU?47ifjcOL!0KkrX%kEF2qGx!0jTAc^tY zE3Rb|BSWYe72iknIvaG!< zU)B`WM+YIMZ*BE&20t@Q%qQbwLt2NUQ zlkH|dR75jxif(U0PtD@)y{A#&R?a2C*Myu?YEg2fV}M#JQ^%F7F>4?ADDn(qj&XceovT zxRPX3%5IXL$@elOdFaXHkjZ4-#u_JLB|zP!>C9~w&vE*9dJL(bLhZKWaq z`c}gtdI%+Ji8qI%Y+PP`wa3)Khv9r(&yVTZr&hB>X55MMcc|Gzqp&ESJ@}TKnna*f z)6I5HW$BF8y%!HZa4*zBe0=GH-L zg7@u)6GOI08hkChn+tdw_oU3-n*rF3WcW|P@>XguFQv)-!)JEbB3*KCG~bv1p_LUB zW!S1Eh$w98n1aWgSk`;|RkdZ5uY0*Y!>JfB-?4dPEXZ2jab>)7`eolFI)~=<*tF&LK=BnWnwHz2v)5Q8l?AV?=s% zqo+4mmF-4cmyP2P@tUbQp}D5znq(w^tVpfJTzk3@m|j!EeKgXZx+!a~5HChsAljj~ zr+PYfHQv@aS~jj!INDR*kE*+js-49hoX*@e^zm&w)l}8+<&lp9QC=2o+A>0Ysd3jl zUt679gB`xtAZVjvBf33eEAQJD7xYJtn>T=f&i(!U`eaz{g6zP(D$Dvz<`R+Hgb{wh zQLWtMN3Kg&U5XVYMc9}0aqbIs^eM>Sbh&+d<#fY}f^PiIz_J{m{GzQ% z57(9TA(&lzX1J!*9_%0_aZ#smY>M*lIKhm;R?B?6szU6;p~|53kp=S@gHDsVACU&5 zPB&0}^fpv+#g*hGkus0yApxYQbAR(v;mDdo@wy@!-kTz7u@!v~gyG=eu+&Ex;Vs63 z4q)5X08z`ia)>$OA$tPgH#8eaEKQYZG&2JOf?XZPuazHNQ_~g<7TkY8ver6$86kRM zT6gf_BDk+ffe$`AXm>u_`+>!RJVX1gkDblHn<6T&`0Hs`O*liodu0_H)(=5wQ6nmt zM#1{m))Ff=sAc`4k#C~}-jZBJ{@i_vb0aWL`z~GpNdOl2`{B4VawiXuQ*#t<8bmb! zlRljPR%AuZQ6l{XFlY*UlS4wEMhayET=;UhB{*z(%ydA`M2HC^t0?ZJUS{GJwQ!Wji8d>+ z2OJ$7U%5>wx=bBJnxU4hwp=x75QTv=)vw)A+xR!CU@<*JV{D7JVBD|>Tnec zH)=g%W^LfRIXKtuc{f!{Mn+01s0lzKmjb%ItenIIv-sJklq*4BclHqh%SN6HH(h*D z>yw;nUq7yu1*4hL83loqMe|M0Xq20Dz5PjQ*Jfvd;<-tqMcGm-xbtO`gJXeo>2A(6 zqRooj75uTY#J;{haMA0I0dIjksUw|1lW-T*?Q@ z2|iOf{GDP51GEf7xqevZriz!T9C_F1j2>IH79sTlJ)i+2agd5)=!n zfDsoEZ7M#xuan;cy$pzXwcFe&emmc&==bDg)aXZ8LD)*bV#9_CB$-s)s$$_thD9+n z1aIY>;j|yHzPBp15Ha@qFMUEbu0E8@BuEc;Ox+waO8C}_-L-;>nZgc$iSXIehQUvt=CmnS0M)Bi z5H)&IezJ7KPE1H>&MR;teqDR$SZ0#45e6~P628zRAfX&4Ze#lKWy8W|198)HA(WHA zb#~x+RyE&3hm_hTh@ORK_-)RQm)RNIO%5+`$P+MQ(SV^0QX1$@FPV`1;C|>Q@#Q3O z2V8O>8CZ_;Dk37HiTKPDSO?szi8ryYME3)RxqJ%e3Io-4>a6ECE!Mb;73XE*Zu9Z+ zCHx+|TQD>-wuN?&eyvDaxpJ&~cC2J)evq&<-zLVB*f%drzp$`y=`#?@#T93#g}egJ zYkmCWi7+iq0i~)bHOU*U*@D{0!(;B;u-hG57wDHHB#$!C=}2z?lweSxo;$HerMX!$ z3|&?2{jVj&{)s(G&rDS0-zc`MN=j;H_AtnrHFBW8)ApLU+`Y()5-DnY9Mo=*t7=Kh z%K|r4waupzG(W*Fl#*V14vH2!SECF&esy{_J3rfBa1`b1TpIdRGAc`SeJr)wVnS0|HVgc zTKw5Xr%@tYd}KT=k#0`3;X^yd6yL()Hgyq|E}BZ+E>-}Q4r^ITWxjr7;^t8Nw((?7 zHm<^+mDL$aLh<4XNR0Z1D(SJgsrvh{36aqEPfL=wda+fTb-I zep}O;0HD;8K>camoOlvVofJFpyM_!L>@xJ{Po+KNhYE|eMKV|w4EhT%AQxCz|8Xb= z1iI06RkGDA7a?$bns&eb3@UF^y?<33ri4r~yZMVI9BN+W#vKJNb~i~uKR30WSgB%lK~cDFg< z9KgYnhv%i{58P}<&{v?b;sSO$zAvk`wM%HMALRfjXR3zQm8PT4c7~t@w&pVL?l@Ey z2glzkcgIGz(SSoaOl=u6v~RfL7G$+Tfo}}gLNsS-pG*9G6k_`6Sq$~kd9k6t*M#v28UEG% z!`K*|Uo17Ici`5sGVmDc>+-{6fA3v1amM=B8m7`}!ciBKh7ifFDoQ6M!0_8v;-9x^f^)gZuT@e|S`gr7O@ z?Wz1HshQ|0P8WQYC%NTWV9=2SF_WaY*mxja;!c)B*moiH$UlCcmehhpE4tDYSpJ*9 z3_DkttOnLbL)}q!(0zPno6Ma9saH>#ff9q&I}N4Kdy^oxXh< zf5f%F7HX Date: Wed, 8 May 2013 14:34:46 -0700 Subject: [PATCH 008/201] Style router box --- ui/images/sprites.png | Bin 194177 -> 193277 bytes ui/modules/vpc/vpc.css | 33 +++++++++++++++++++++++++++++++-- ui/modules/vpc/vpc.js | 1 + 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/ui/images/sprites.png b/ui/images/sprites.png index 156df1ae30d6f813272804c48642f5af8da00af5..f3c8226b64a57b5bdafa114f8b2050de85a225a5 100644 GIT binary patch literal 193277 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

GK+At)*M#b~0!>{IqLqpp%Jp%Fu^Dl^JY0Vk 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

ctn4T|KFZS{Z6Z4!1U z+5RsM0`MCxcfay?s|;99p6`PCazg%(E*bIB0+Qd-fc3rbjYe<oXeJ*xCvTsisbA+)Ry%eSmaT9WOu5*1+&*rih+4Qo9`+hCuI*~J!9>(OW zd+ilXp8lCOa?I98Sdf+2-^UPX)8J0z?ZV!F?-1Di&^Ca_3 zj>8`a%q=W{sniU%TdxPey!g}F9+B0>#b&3K1~Xv8-rIhZArqbx;ZogmL1%_Din z0h=B68=!mKKrsLWk)=V96L=8SvKokpW1nSX`)W0*h-~<=b}EO>2-@#8>xDg+Wnj{X z?m9gNa32T0vdlMXt<4$D-ybLUuPvxSTGD-S&35mDvot+zsFH54*{{!2$wO}0CFpq! zC4HKACEal#d{}n|{t`TIHR*HRdK`X`I6kJctoUIcKeETREK*1xq><;13zx(^uy+O9 z(9j^?wH<^aZ`ROyz7tOVWvl{%bJ>+J}g1lZh00{*-z1&K%pB2n}_x_yAHXcSqSe# zJcjSlM9DZ_o@O#w3<}fm`jE+`Fo-$;q1R~@@B2c$q z+-859%oy;MZQ5%t@so3rpDuO|Iz_23M4TfN^+N(RR%fIxGydKgfVX&Ak3s+Uj|B`m zgd$V|WV|38;!gcX$u>gsAV7TLGf$2&y(c<}YfmJ6--n5`~s z@)_7em76HiP{Eb^Yii0eHpJIGNGAiV#>Vd#dbT8j%Gz^g2;FL|aNUojA@3#q$=6TH+(WH)ZD*ja(s$#Bp|>zUNz6|3le6Tn7BJGT{&l+UcsT*o zpN^d{;%?&jkuEtoxr7X`V?B;ntdXe(RO8u<<@^WU`t-}|6dRb)5(T#h=L#Up{xz$A zrb22`R@6{!7iR_dnp_9kBA&HB)p=Zr@KWMnsTM{*O>_i5yzXfCn9tSa#2S!X@ZuLNrZ)9x$a zQg?J2D91UWI4SZ~0MrB@^4m&Q-uM}m+~7VwX1!d9ax*cV7C%3G={&a{(bP_Cgg@N= z7WAV==#WRIOz-)dWWRTDg=oY^2#O;zH#PlZ(CKj{(QE*-wwOste(I7oWp^GkWo@fw z!3&CuvCSo!_*>v7d2l8qXBmd5W??|Bxso7=IzKO&`rK@Juq;t4?~ez$@8htcK%`J9 zVpzT1#%TJ07h)*pvB?R^gKdY^D;jxM1R0O&uN@NazORgyv}7@7Hhdds2L=EODBrxQF3!=u=jTGOb7HU=WnSK)O`U*z@93qPMFC|A;6+&zKV-#zTjKlyiRr$1cU+Sv}}{?wl5;mZI0 z8?CL4pPq?9eB~FmsfGEfQjeiF(FK%kJjSTx&*;U;++qJ5v*~&hn=?t7v~0DDUA>9$pDh<{KmDB0^X<~L_E`IO|XmhYl+OVG7eeJ zxyHF6fhSBnDiNlt2(O}1*h8>l?*p6QMffd2G9)a(B5l7_1Vjd#po!Ezvjq6?B@ds_ z>fZde&;MP3_p<`+SECe%l`OrxPt!yk@^B%0gz*nViUIHaRE;zzjK52Nh9-0Nt2-JI zddx)zC*t%vF3(>o>)VW(Oydd6ibf0{o?|r|?SzL@(v9A-ao9?$P@#Hyyr(V682;Kq zwS8&u8SjETd9+}Vh3Fcp#oM+~pcPTU+B^6y=E2=1SNSJF-9^3Bm;OERGwfbZ@J2#EuNnOPvT0ezH8}>1+qd%{NJ1ZCtz|Cd))q zaDLmx`t-@ep4l5lq34oA#CJTBP}GeXTlUQ(C57%&($CVBQyf}Z`h8JnJ|v3Tsg2f3 zlo9+x!{;N^h$H|8j!=9!jYw$`^D4QW9Cu&1|4yxEal#?t%hYz2yH$pEQk<4aBj{KD zkRW2CKdxJxOHWKsPa8td>w|ie3(bG}^Xx%z36ue^5xuBgfV9zuS?j2lZuk2me36L{ zL#vzIT570`=|Vq+kdN9R+0n{Y*VXfm5M2!}#9ueb`MvkIh#vdeQ>J{0=IlbeT^9;NQSQnE|#e zlEf`e3>>#ljXD)npmtIy)kkG4(hn(58R3PmtN5a=yL2~<`ei~~?$nyOms1?d4~}U+ z#7#!_i@leD4%h!uYeFMvX|-MkssJ;xc%SJ^VH-j0lJnfUt|H$$GmK`wb7KA`nprYb z?cKverQRLp0Ch?--lsa=?Vy9Z!rvuunVFgQzuhD$-L%_ws0QPnxV}sHd7S+?M-<@J z?;;*3wM~5ldRHo1GbChHus=MS>^#s<@db_Dr+~pW<+RvB&ec1qFre;+hWx8u7W+Ai z_C!6EI+QXqfioeNoH4SszU{_-Y8uQ!mVnL&zFK~ZRSXr^gXqN-emvR;r*%@?d5C^L zWD$w~76C)hTkr$M1CstfRgdAomZyX7x*DY#=<3Y0g|Pq++qnF%D&z3vGgsq!P8xb~}}q?*%Ba>g~7J1Mc~P)gUSP2mEBJnQ~~- z^E1F+ZO_&4edCnCL^py@w&*52862aUEq!dA5e=NkVe+%t7#Ny%DxTi7s~zw=OF<*k9LOJ{)@!Ew-6OJ*gJ<8`=! z+|EtN1-zFRy1R<}N^#(1WfVStvtqwScDkGyMs8|CfA7m*;kF8*nBVkUv%QmjL~g74 zc8=?iEe-KLP5@OXsl1RhEW5&bUm z*UQOqdlB8F;v+#{676<5{^WK(ST_#ih9T+Z8>=UV0*D%)|&&^%<3Ega(lKZ<>;5aHdLOrQ!bBxkaI?4 ziuX!;D{I5yLx9g;)_d(@ukBzVUo8GHj5p z_BxVG=^3mH+PUA{=NLus z{xk^;Nt&K6AI3C?;0jJPpJj2)hB7_6nn}$ysIZgJ_3rv>Pw0Wb^SC71vbAVBY(r6# z5ARw7ia}>Q0S!_?Q|IrwpU|M>B*<{Ydq7-J5g)!mHDync_~ZcLM~VW%8uePx;>O6y zDZe^YMnMe86F%Hh3Qwjt`)b@grlYC&`^xFPIPNt%ci(0*V0}y43dO-YD-=b9gnfpH zv0Q-m((ec!(O}Cx!p+iLVO24uUWGrLc=gTXnix54p1)x05;QKpwioib-E)EOF?vQG zk#Oo9ClBH$49Eq&sfz;CIx4R2?EMDFVC*%_Qc2~${D^^DzJ-**?`JPt?{73@@lx_r zPZLFMK3&BW1SqAk!$HtFp$PPdE zE;oh^8m~fZ7+#cJP!rjH_9cqoXL4S&@eA8V#Z&NZqwF zIA~2&zHS%#WnLNfoKFHr9(h#(bMF~#~7Dqe(p)n};%&CywxUq%?X{!Y?-#{L-kpR2{1en$(FBDhxg zsX;L{7`p?s-rwN==VppM*NJmF!kOsg|_tA1O|p zLDakumo%^s_;W`mTN`IG#8@Nk&h$mB3@1X5#ij)ZS8=OmHyf@J zp=rc?YNnBeg(XT>QG}Hh{<=pSf)9P4{jA_TSMF!o{yZ@_@e=vpWNis~9Ok&^jt{ct zVZaPXeqwMef#Yv|AkG_TAOGspT85-oRp1_Z09(LR!gw6h*Fe5DYY44>ao`*6s z)7%cgQW2`I7Oa7vfjBO0u}iqUuE@iJO28Pw**-=)G{d+~j#)=nHnc zy|r(#gN;65ME(=vyR)S0nbpm39W)is9620hCva6Vb1oEVNyML-16Is%2!6LT`y31{ zZJH*fd29NYH(WcV#DCgKK>pzIa@In3-hNs$sUY(7H#S}0>v*8l%BvOjTAG3!JFF}w z0K)>96T@k)V2oY#vEbyAkt6E5u^=Ld^muP!xN{C6UCd8bkh8-7_0)j(V!iE#YNEk- z;A+)V?KNd=zdnoZ@5b0+gt`#&%j|&>G+`cl{jUQi>#QP9p`nk`Nu=aq(Wd0)+WRz<3G78tWwT+<$$7hBWs(x8$Nt$ZoQ{#JJXu@t@JSsZ zSpH6K_Ft0^6?*g=3VfZ@9m2iW;!0k4KE0;PtSl^8MAvb{|KTOPWl;cVtCW>#6a3k^K6=F1a1C@HsIO(d z);0>5nW`hb;@tQk`smXybWMOBj&r(H+jG-)nCorwaK6Dk@cJyta7iAof<t5K>UJ(YzzlI|T4-`mlO$N9!VGrIb_ak*b`Bt_(;XxVa zu5oU^=FO0q7)`)h)BW~*npfSm8&&EI6n@C{pj1lA%{_0jHQgN^u3U~GEq#kREAt__bY*DKQ#dst?~FSSr$aXQmXn8L}rmm(dz z;;B379oFn<=(BVtn8FYALR$B z!w_8Aj+!zd16#qV%U^kGbLnMYY;DhQ6ol{Qi)?Le@rZeBe#v7!?Zxu=-no)C&?6<^ z+{_*J&0471oQ>Y5hEQbvV6Xc;K;c6BnV$1&AP0#*+-2a@I6U zuKBW^Xf@Lwnfxbn7Onv3V0@T2S|P3_zc=`Cox+ge2Xd5AX8)YdqO<65QeM`)?l6Fs z%4z<`1JoeH+C@P}XJMqRz3P})^GOhSH2FC0Ze-Bj#93xSuofch<_wV*(*gVWvn2PZ z)*I-{=fcY~hqZ?zwfv{GNC5 zLZUXiZh@16@!_u=g3J43*m zF>Ha)H>rnnqdYHZhNejvkiEMwKZgru8_M~MuJ6+Ah?{sCAmMZT?m|Z9Uvv;Ahaj$7 zd0+p`4vv;m$=%L8J(*tC8<}jYRIGg3&wW2#?-0smJaSO`#=m1HscBZpC_xyxl7!Sn0PijHPkCRzNx{Y+zL%GyE^;U-( z?9cw`^w_#w+;Op)%E+D<5^qF^SOO46(kWBExWe4Eg>IT$ltS|{k>2MfeQZUT>PYpb z1Og|E_=v(Uj#Th?x~V{pVb$kkkE%SXcY24gr%5ah;tz4C{im+?qlJWInklvm`);US z%HsZEz)_xNQ8w{)8CU$a=R0lr z>l1#|cJCksCytBz?>$a+ww>YdC~ni`7QP?kTtQ$Vy-xo8iZvK0RN>x33UZ7|z-5K0 zbq7L2XcU4eo!T?=2lVL#@HSO@oOSm>VRY-r%@?l#TUM+E`=JyLr?Y#I>a=;s%k?KS z-XILB9cJ(gQh}BB&mvL{XJ58Us%PJ3oE+5=!793E0#~+bUIi$|x(ixL(3mv5Ok4Zx z0rEfj8ers6YzHZ=QDZvk0jfG?fq6Ifyt|^4$N~&bSo{ouMaCO#qjDk#`!x_5v6K)X zw3U!GsdS={2IiFPW1n`WFd2^M$&uoZWPA+m$UgM=MYimvs%?FVD8lIx`EXQszGYl| zOFXVpE=MX@Uf?(2?RmV_I?{(R%-F91suG8p4C-r58|Q#?nirR_Kea$=o;99L10#wAZbH4PQdy zFV`AXVixa5yHx`J+0*}c;}H2Uo_TWq%XrpW3^zGk2q>t6s*fs;S-0NM*)N#w8@;(~p7|gmr5|d1&uV0J~#yiCPYF z%(4Dzkln2k-0Eqj!QcgQH*CDRh)f}Qnd@^`?D1t4U&oKJO8i&O&$uIoIG`mi%#AI0 z6qdE|cOgW6VUFxXcA6JBB$!zlAbbfRKcW9f0J6B<(w`FMl?LVyspEEiMUs}U_{QwF zMiP);Ud@)7?~#~kU=HEC)eFTY!T#4p%a1uVkCNNoe%;e7f%kN~{w?Y#z{^w6N4XU0O;=Z~fJ0Yy zk#kC>)_&VIRgIq^ZO^CmOt)dR4fj3pW*zp!vrk>Z09Gx@fq7G&*W(vR)40u4{`3%e zqVsQ5GY0 zlc7u;Hnx@VQ|$*YAu;8Vr6Xg^XXCf~`h`vWoQVl@ME&kaes&WE7<+aArIZZOZTH$W zq@bi71bkk%aN~t<^&9}T$ovhj>uCp3_obJWXAm+_WX{=;7~HMbC$F>~U#EZa*_&%j zII)0mosS_tsnSU`e0iuU%(w^VaS&Kgq=0VEbC3!>#YPfNY9#i(@31<4)4umX(MVE< z%TS6Ny&dWuZM#GFer5LX1&$CX+3lRJir=(I>p3fDm$H7igRdw)wqL$n0}822@?(us zcS+YnGHv{I_2VsoSxqPVM^O9YCNBG&41C@>U9mkg1DfM9A)#ZT z3rw-xe=#`)7d1HpM;B5wko*)ceAxr-NXMZ(t;7TNLF@mz|5?a-r>boq#*&f6B zpmlc5nC`xn{u})QdE(w}+tEu*`B?e(`S?C4)rO91QGgV*PB-k%FCe@ecpxHi%xLBd zdb(_L_}sK&N`KeRt&bl}rVn6-Cz%0G1}jn|%@hJvaJ4tu^{U|vaC#YqGIqPc+nnmi zEIoI+*Wyga_j&kq`Bz-?5o0Eku@`^z4S^J8B9<{Br;pRaUwR&srhAZc=PeD546P%! z!v@2|lwy2p>KwQzb>qPn101NsB(ewF*6R66o4%nL$2&CnDbZ&XjWfpb~!D+(8#ETi-`N2E#v$F$_$#HSqE*n*PZQsQB#u7QA69Z z2aUH52+2aHd$Z`cm`EQ5AYkPja|51gZ)0{B1feQ^2{umdH|`D7QqF* z`MH;$`iEYL4Ou zsmBJyg=TqyduyFJb`6)Zl4wi&BA@^qp$Ou{pS^@_wTj#s?vcWc6Ud@w{c}3<53{J~ z?GWe0>7SO{+QT4q*o99;oTbINGBYx7!obZ^urzQ}Cl;rnzpH1Od`wpP8ae>Q4{1aI z?g52jj6f*e$DAwtD}~=@@bJ{fEyXycP5K7oU1a-adKoSzkooyFab)Lj)Zx05ANj)v z%{`ZGA1W zk5Dp^7ZPgs>%OUmH03qRMD$!h2gA^M-Z}*r&|ir@ zyRkDOBVM3>C$EcRD2Cl}ue8*X)KRwXGNm6P{THA@N&y*jDar`9?Q@xrO8mVx(wYFS zi-}Gj2+?Es^MnN^j#W$oGoiz;BvsGQNj65Dv66UlUP6i*&V7~ux z^dyk?4;G@I;Pk$NGa4LdaZR-U{Mim-OBLvbu8y9j>8cP^N}3|HQ8bLbN0m7JDo#xg zN#d_gn)}J~%pKAnZCLcBb(c}B;I=QYT`3e;^-pc9ww`jn-%kz3q!2#PVQRh~V$@Fn z$YqF@e(q_b_dAcMkAF=X{B?Me=H$kJ9Yd6D?PK-28hbwGLYGkQ@Vu(8A}0o!}Xn)=7=H1>UB;aa#PuUZQnA zLgnU|eBJ#15w}HI4ul^+b~tBkp6wf0T~_=J2QMM`qY0i_m%EF<-$U9B=(Hy;i6qlz z50W#DCZgU5n_MI%p$f`cQ?0HjEL7TykF->g^T`_nLC}`4zi(po{x)!&YceKk;*Mi1 zAz-$q&0g$ry?CfjxY|R07L|?BeiYEWHdp5t6td4Nj!{q6ucPIB`*np;%GGvJvEIQ| z`w%mZe7gf@2C8MxyPAKa`6QXepHABFo9x;=PNcvmK{r$~+s}L;^x53s`g4w*8B!EX zX|*cTwR97*yli#Wtm(OCz#n}P1HZoewi1U0CTOLus5iEvYev_yN%@X>9{rw{J1`RD zXg|@PL3vF`O)koppXQo7(oKoM?>MAlZj9 z%q)UMAH_Y1qu&wHi4uiB`4YH}xSzg_lvpPGT14&6sF#pmeo7Xr>rnqsQ3J0;{K2vT z%c214<9h%K#=LS1iNQrI>9fI>p6mSGwM!uEcDixwqzRfG)*vu9P5gT2k&l!iMKheW z5Lz`tCK zG$so)W_d0ZnnrenZK-bb3Y7YtjD-+;h9v!WeB6h0+f3%s#I_KiJJRiw3!E1rvd_iy zq1`zS)t11ik6&A9S@2J8c>iDjOBq1BdrJR0%~`)yK=g`%3JL1SxEa#+O2zN}7hLN} zxB6^<2wCvVNbt(|f64o3XM^CIm0X|6;M@jHL7)3%O~CA%pmMn(cW#yy?N*}wsbR@X#A+0{3ASLMuFESf*_%Kj=#-&+j#kU9{OXZ z7Hr&};U2Zc+V>G!EKu|8ci`nk0A`{4@N4I6511pyj@l!W@S|DfQ;}pj&#r!y=N1&; zx~_OZ@DdhY_Jy+(Z9M2cqbHOS!aDe=Yet`9ihugoG{Rqk9<1a%k*EcyeR*i|v%b@b z@Mm28Ud?f=D8aM5t!8;&__pSIi=R=Ss$5G;in=QIo{{q+>`{K|-O@;*HNjB$O+&}L z)2(b*;;nr`SX={u!6KJaQDa3nEC%6vJcOHmWYo3lE2Gavsr*)su!;NaWgx=JiF+Etd3}konbhH zY3x7Mxj#BYJ;1KNIQGm6OB^sg6Vk0M!YdIV(RA6`F42xbFK{RS=cLGp{ib0y;?IT7 zFa)b|1Hj9PR(bww5(#Dvv7vqr`dEiebkvpZiU8jzK)C;NPQri2elw74t-l0ue;`ey zAV}JQOf*zqP0k1j_>7DMA@U|`b}PJ5vZTr$XS#bD&IhRaHVP0W^YCJ#%7*>d9$wtP zZ$%Uz?AOIV)4_i?HTgJjRgXjrj8qGm!tU8(xVKzLket!JkUT;=Vdi&TS=@8$@z%{< zdXu_95lc>2oZ!i0adX;Z`ZQD8$c?8R-fazY_tN968nT(Rfscfs9ELZU9uf5daD(kx ziq|5_=+3YT)I4yGxPa^XPj3|w8DBC#thij18@fv1T+7^uJXdCK*1rf<2{14=kJ7Xj zaz+|Qk8#e%` z@IoI%p5`PTj&CIRFh8q#)vS~k#c^Y+GBXlHPNu6Hr94hb8AsATr z(L%Rc1wVh7Vs)%UCtF8H+efd2n)p`@BxKLfmA>{(3a~4H+O>fW=M1G?dm!PL#R0n_ z6x>3HKO&shhrI?0VpeL>ZS0H+Voj_-^1#Mz8t{u|@KiJ`CrWoPN|;hbbkszn8y`~r zoZ6wlf~q`#iEt3(grqA)0(=bJlD($*L&@r)PMt$0b(l2kQ~=javN<&#&-a9AVp<+T z-U~VU%ry&=)tO-Cut@3(T>F=#Rv#LkGomrx8@+UgcRn9g0`U0bibdi<(XO}Im+ON< zuenWrlPV5yCt!-c3ma`c3k4@v_e)A6SyE+z@=P0yc8%V8tQ?`?`M6F-I}b;<4=b8f`_B9`KGst*+E1B%&72SiDi-C-yW z!b$btN;lls0MPzGeGk*~o))#9Heey1R}_eq%o-L2skbO}gb4oTuri_ZEZTwj2waq! zf#wd9ke^bKp7fRRwZo=|+MR%B%pF^d?1`Mr1;L55-^nn=6g|SqDMa%l5RfF~M|n-a zN7GqR73B$aiYHObjs)4!+g0n%8Q};%ChY~m5k0cRL|IrOCiXlhyUV~`r4pDeRNBlK z>ptILs|~pO900MEnm}FcK*4h0;0+XwXv(rJ*$7N%l;t13h;-NNn0SVS9qXf`N(+ut zky25U4$ort2-m@wDS;_(A+^y38Ww0@r=7-UANm2Gp_?PK^weo)pte(xH>Zph-9}lM zdzbqF^gItR?Aa-t#ec3XB{7I$$*KYFyo8$W3+xD~S;?rh1Up-Wn?u+cfmQfKCtfz3 ziPlq0^?~A%-~UJee04Cz%IYy?CwN11fGlj}2fB;sCj4ODdO#V_T=?13eQ4`l|B)9bv<3Be9n%AqlctM~32oWN2D;n0!@g#3s<8@A6wyi~&QP4OC4 zJX4v%{<5kjt_rA1d4igE*Sq~7M*tDgJuMudttR6Ld1g3kRmlk@`IY?KNQ~_--{uR{ z**T`ZrWbpcMaxBA#NantLBjG7U$L{E(se0Tg{W$Nb^^yC46{@dg!Nki&eQ}LI3#OD zuZmo_Emm2tdHkSHcXu+=6{15QkW#IHCfggw;Tg#~vk`;sR#vhI`oT5NEr+e1(s~0e zKMbzy-}9qEN!`8M@bMVAtR|$CT$AWZ^uOSUM@&0UG0%aY2=LNm^B$p`QkvsK{16#Y zR5CuGTCrkbNzP9ikVdAE*ow^KI6}j0x7N(1lXRuK3BzEw2bwHeEm;On~9G*q2D%-U&*PeZnFwBIytEpZ3m2P1wkJ?J(zuvOIPt{9R8$tuiwd(e%|Vi zX|E)X@9XA_OsGk3;QF&|%%)XuUKj1iJ|G#OQ3b0VH-VLOcGIiTtiB_nd~=|XYQRO0 z@niL@3mAI)dO`IK6Xc{|7QUNlY0H-R2+8Sv%M+pv;EAIx(oe~NWAH2B+tvM955<;o zW1VAWpj>N={EYuiRCE&y^2QFi3L{EQ=8Uc>pucJ6b1ScyP(PX8f*fYkqKpx>Tta1n za3p|Txw?<(oAMOloSkmN$-xnkHabf5r9GNJBYZM~-pmaW0#B-?d{@4%H^1^l$Kf?b z&F_~!jpqFRu_2KH`3fin3^C0Y6;-y)St`6U8(9W})M&}-&=W}`t@{9q22wf$StUw? zFiI~U|L*Rp4|ogA8L2Sb{20~R7W-r%4jHSl?6`J1IKSzUC>PAC7uN$h44jGQix&%gNwX(|zoYyNE zdzZt7oyvDs;4(Ix^AkG;G^Ce;r5*-PaDDU^svwWqPg2>PZx zA@2=OEUF3L3MGx!2 z>EHQ{jg2?`B%-e%r&{&RH)ZX~`T0BR8;5fR_$KIo+#(*C?ZU8MTOwU&%r9=vOrGn&&l*DMaOgxbYj270o+g&7FLL;Q!hPRhoD5_5s7~4g6+C-XLqsR2!_Q*KHi^|GJ9WeHI+mN;8=i! zziI+Y=BL;o`pN+}P@BOT z(W;|!q722#l&5oriV2WV7L9*tBiu|Dx`Gqv{hJ99Ux_@IYboWs!cSu(Bjc`OHu-#k ze`oyc>t>|l@ntt+V#ipnPr{%bG5`$UahQ2BG2B{OW{MZWOE8fHrM<-zT%QzsXX~cp zV1ss^zFtq<#qD_YA_I3ZdE48i3P#L4hmTd_gJ)vf*KE>MG9gnIYPSrXHr{ozh6zy~ zrtVkCSW2+Z(SRzi@%gHHK(N2g_Fe(&J*!%k6&OBstQ{>!%k8IGhR3EN%dn;pL;kzw z)#ku;k!s599A;?67~+&qxV3C9wz9iUpW{6{2FSW(y;iKz2Ry+Lg2{ZF@%v4{4@$i5 zc;$o?cy;ckgwNnIpsuL=-s(8O=H+LA3JeTn9+Ufq_)o@>iW;6nHQi31QLn4h)e_o( zEn8B?EN6xK=~flH1RN3R$R-^Pr);2(!WB$tehqlW|=n37_ed@miSg^MT6n=`SaHHHnC0#|tReL*qZQA`#F#Hz_JtVp)*h zjMq8aDkDjQUAYH5Sqerf1n2Clr1O6XXwHSkJihP8=v2VK)E@~6%x~}((1P1O6Q1Jn zy~74mA>aCxWLZZUX5|X@XWvwKUphBh0A%y{yMB9*KrU(G+b0P?#zgN;xa7E@Iw~si zHa!=S&$NG@!A5RyG@vDDhg2Y zO);H>q}xYIBq(i6#whv@G@GkGrjpRo>e;Xhf!-bp^QkEWdR9z|pvBtA=jhpbU7mREy%nK1jjH`;bF^-n(+s zkJ6oO=%mg}WNs*Bti00H_Bb?E=zUm(P)Ec7w(Ln6qr+OKZc`|ygE?4yk7z1rXexny zLm7RC^Jl7~D=M*)0!TKu9!uzxo~d#Cax)0yvJrej&fw?M29r>-g;x8{Jq3$LY4q&*i;Esz9D$4@LW{+US&xM>x`PVz`g&Wt}n=duklWU&l7lmb)MP}1v@S>N6`LOJDyT;M6=O=azWUdVLufGd+~QA zxI!O6N4i^3vs+m5kD0A)G`CXwx%u>BE*3Z;f<)zo{({IF*HC9OBIMLlXt$H-!ZlvN zU6tWS+|)ytT#u#CA5-g$_Ih3ahB)%OwPfB#kDazJ@@Y%-lW1HJ)t-N(k7eSTBasz)z(Cst5k<;;4HqVL$UA!%;jWiOYpY*>LR^yNO@9PbbAeHUiRo z#PPD1d?z<0ITKhVs-O3I>b|;9dxd2uhsOufkP2MmSRK#e^JAG{<$f1d1Btx+_)?zB zMq|zczyD%-0Hyq5Qg;?VSVuFAh3LcWM;zP`&jo}z;iZNrK4|}1XpMr)_IWLn9ZC!K zd^?E(xSj=UpqARRk+wJb=X~L&7NR5}9d?^~C|UBOFYR6y4MBZan;bXRXGvq6**Wa~ zE-TT$KKe7jEK_IA)BEwaV6w7mFgcd+c|0*ZSW1CJEGcBEJsd$p0HF_yFqjOG<%@-x z)$^1s(SzqreR=DC7Fb>@te&+4MVa~+&1t7%KYGz`rcC=WV>p9BKL~vVvLR?)irlQF z!Hw0?iWbv5&PdtCRHMvzM9J4;fqMb=^~R$WGyoZj8E{$OMN5VljvzYN z5IsLP3`P!3Xw~Niz>SqFkq|Y@{GG>aJ1d=%I)6c*QKP~VR-HVv5oh*!1tnFxjgo`X z00*5*2VX~ip|#PD6AIt-O+CC zFKm@a(^-B{t`%HF-T#^lA{hVvgEbb0QOx{zav5gf%D+`6cJ(PQ4BoXJI z4F1Kpx7zh>hJYnvRiy&M|MV9(6;*!!km0@)2gaIXh7ruk@+$6-udAc|;96tFWHn_Pm|8Fl!hP~YO%7@nh#rBxqmo4W3IjWKdI*d4X2U6*Z0OS_YFmPgI3 z&KvnJkU$-sus#kJ=BvF1MFCK%Y}$MjZ6D{>4}`v|=N;F5GLTs{HXPinik#S(=!%AN zN!fYCtG@*k+xH~`2>H}H67mgD&rbds?a!P}w0VW+`2$8r*@f)9BLv>vie@aR;#pE# zb@Vw&dz9r7OUE9ToY>3#c>SHxaOUIyvh1YtwZib%iEs6e*2+aY5ZHpng^>J@*Q``P zAnNkIO6IwnW1otberBKobztf)gO{56kG?g_UQK87Uq~_sAE;nzOd?o{ z&UXx*ysoEdtm4;c`p5FiquxMI=a=Ujf-O6zsJRAmoxQp*^Z@U1mTLU-0|pa#$BDQ& zR6C*gbsZ$?eJZni-3v_bM4M6@s(J*A5@W)sys}9N%|p!1AS_;QS1;S74*Uz}!ROIG zm>iDz+;5*>^7F8sugbqvA`Mxjj!zPHED@>X(C2LB%VwzQkQx5q!t)~ks2<&J`6VWo zbF155&g-UbiO;mET3B7^WKi}fCk=&#oo_M_QY=4is`ETn{idK; znLDo_h>C&Iuc))s@5r0IQLrn2q+x_K9Cr*ZP;7HQb!DM$Bi}U_0 zMEJroNW#ZLg8W(-u@cG!jna?R08q*cIB8n> zD5~WxLZ;qk-n7U;WjWig1kEo*_3WaywkH12ZhSpoiYH;_+4{V;zVQQ>$K|xx8v#w= zFdjG`pmQS2xHnb2X)er$ZeZF3nKb3jIes`#JVxvEdBvrM8qh944hW7)^aFfEnqhY~ zx~wDUh&sN=_&z+Lc)BFwo6jq|nBARA!q3mWe`6)IlqRf?p1+n)>F=9X{q2=4Y`-2`f7zE!4Oddk&j- z*^Um3dK|{~nNGi~Ma~h!BTS#`UsEW{fb6r}wK+&TZGBIc^QR#L)Cc2ZgLTtP&uFS*;N^UEw z*I_v3S4J$Q-)jPQ5Adn7>_3cPX;hohM{Z}3zCZF!#`B_)Hwv3yQbIr6W(&7%Yzef%|Im}UUI^|R}G{1$-)$gl|iazAVM?F;7!TN!Ai(>z!+Wpse zXzWh?9$Rv*bmnfNZx1Re%GEmUs5M1VyDv}eebl$bb~eb-)9`;|X~0P<#C{uOaKxp59J;Bv4-ant{=PlCW%DcD26PmCdX1gX z%9v@4q_Dc{$wFQCTSQ1f(5zgma7@z>{Zm=~;X2$_Sd)}|it=pMt5b|^j@<8%!0!Y6 z3X&UF!hWvOkRfN}QMT(=)Ag{}ZPrBIIq2Z>1I>XF1o&0;DhvjdGiJmVGhV?X>bd

3lBp;caQy?{Alb0+<=M(7OT< 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%0AEb%%{5pd`3)D369ccSoV}ms2z37 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 literal 194177 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

  • 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%0DH)j|ok;)WI5(qP6q?T2QO&du0Ks*!l)I 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

    DvSsN-8#Tf;UKP+P! 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%0A_Sn;f34nstiHp3t)+(N;%$Zu z66mA;#j(ue3jSv+h-uZ8aJg-d$?&i9a9gf>OV&uu&4-SRlsWWh_m8>VNFe0)f$R$~ zqt5L8vB~poX~pj%5jIVIck4>^V!jWpU_=XX&Jk4Jmw)FFbm#2!?!bG;(SE$m*C%FU z6?X5|z2n}U3Yc38RkGu4r`^cO9Tfzc5FZ0&xm(T`+3vI~0)@E-kERbk~||MR5p zOc6)&^4=E`!$=RxtX#IKiqx;0y^}s+w&Ff=Vb^(N^UCEgC`}=4)=<;|OU|mDQXDwpjXkQ-2*y2c}3Uv(cj$fC#J27w7AHk=umT` zJyNt85d5f)f}`J~`YvjX4X8{!dK8K19+l|#V9Ua+roahUqDW?q)~EX>^*M8X8UpXuCglqZwycU ztGCVxwA7f1CDK28(uH+eQ*mL+n2USa#n)IvEu~PfRlr4&$G9ov$U|oU1Ghc;@CKEf zPc=ACSWw$sn11}vwdCoO&KHZ;dH&sF%Y-!hZ&`VIF3*?QEuY(O)!O;f7O2}Q%UAE@ zBvO+w1A4uo%aB7^|#IK|gOn-4z$xW^eb$(UQC+tZ)Jnc9f8m6!Syd;v8*4 zV?^7|o}&aeexISrrSc_c0*^bUa$Ho!B6lb!~ofvZJOTLFzgz-SFt|JE)AU z=}#5kXsmC`Tz3~{un>=%fkd_*7lY0A@H8w8aP#%Gc2EORnkR4r1*;NGDy7t^62R2R9IZpCgK%S8Si1_6v}9c+fi~&cqF!J z^oAkQ59NjTlHyk3HUZ~Enw>(!x2CC@z<+ZdU=9c9T~W89e^=5u?iBXa{BWvOL;8VP z4w6ife>2mEe5H z3McRNy}>Ma6^qyt=d5UY6QJh-^TJt>((B}Q=y{SdYQNxxvBkw@$k41^Y&lW1VGR5p zaTJIICV)Kb&;!T=?9NHjKJ!a6PGdxVM}u?5p@rXFV8{}QSC=Ijf=YF$tiPK}S>w(% z!k^-VUl${HTLFlnDZtP80j<1;<2Fx@`tO}PeKl}r5AZc@Jmcd(&VflB_Gh>cTegAg zW=Z~r?~o2vW+UTy$o)r9=Bh+V$uTxTwuy;N+&+~g4V)akfwXyTma=yIz#L=kN>uLGB~XzR&SbAH3O;%`R&K zeJNZb!=rT^Ey)7@2koLnN{TUnSNSdPO#)FR{mXP6a4-+Z&Lmjz~~ z<8&P;*Eb<_xC(%TM)dIWF`I$|!cxKLE)ef!%%rfOpv$pb(-ftP&}Z)7br5=Rx1Y}4 zfnr{bq|57){?;%xIub$ZaQ&NUB#O|~im9^j$9Hz;L_0=RGD?i|7}Ew)gHiRN#}#cG zAie)hdK>|O?92ROc9>%6ABl_$A*DS)*NA1?&0+Y!qZ(Y$fn<$`9#2@}G^O>zrkNc`0gL zJldl@>;^*NsI;Xib+>a zG}VS2evaWtRa1I;%rZ3_uYjN{D7u}QJ22W*T)1e7VM+@vJzA7+QEs%}qh;m;3HOg? za{_G#&B>}*)|{<7Z_-4UmIuoEW5-P~btuSK%y_5;BHE0>>5BXu0>%y35e z8C0HTAp1-93H8c`ywIl6fN+UtG1M-ko!^ch5?fv$x|#4(%vf>_BpqRRZhrEwK!USmV*zy_8KL*-t$Iw*#bYXUVLLJctPGW+^L)V5cZy9 zS~07u+W(j-P&^!on|5W+3{2fE`Uj^dU`XZt%i>@$Xw?e#W>{2Za+rUfL8^5+Wn#)j zvLl$y^-mN-p9==?C>SShdkBn4T`vcIEN{3^3)pSfffb{#b_-T-pBi!q270~DI)6nL zsKrG|BF_6xHf3}POvt?*l!L&?Ce@ndn~o(>n5)YuW9`Tmf;C3uAt*-rAAR#jfnr`f z8br@>4rC&#Ykdi)ml@C`q*tZ?rUgtKTP+W$9`)*$>MP;++<*kUl$Jbfyb>!?DYiV` z?aQ0rmapB-d_0IlMM^xO0I6*QRs_nKLKAy~^Yk%-a%Fl&YSk_tZcz{CkT`^A9VhG! zDc|Wl5Ruv)o*$=${0>Z$RRgYz0~v3QxG-1Rc?P1PqAGRqjI}{$K8VK(=yI~Ll$>tx z?JLkM`39T(?*`#;+CgGWa_?uoC+L<$94W(lW+4F9D4!9+SAQsOJFgIWf^#`}YVX<4 z@77zZ-hA-ML>MaT(CG{CzDBL&b?}W5Ky9+p;syxTh5a z|Jd2*yj8d5Z`wXy_hJb}h;Q4WW|15TIosjpHlx(6#x-b>`5T3+IO5vNM9ep+aV!kE z81z1-FwdI%D^8#DkM#1>6#$$5`sZBCx{P-~gbILuv5W3Z#4CH&E7^@v@@a>d7kVb| zhX;PjG0LikUix}-Bz^QuJ@nqs)dKd!3o>~&1Ms;BkQl%GnLE>!3Jn-r_kJI}ZQVA; zwWoasXkut$_|vm#mx$y_4d~7~#^-&eI8WM)+L17^SK)VK+DV*Irvz-|2c#69!tfovSTx(Fp zW)J+0%(mbj1RN$bp|47U6YJlt%!3M~RBj*s@Wu6NgD*$N&Hz)A%+~A1n&X$hLQXNK znGh)|_x7F9_AT$Ud=3Fr9|ACTri6~WG_LKYnS8I(@5LX`SLB&7eb=uQD^4G8 ze~`9C(U(f;@hzRpfIIMsm(~0w-Zy2t-CJ^==-+%?n)!JJ&MVABT^3Vm35rlQtJFTRJ_(ay^db=M^EEW1b>xMDpy?Vs2E++5q zwz&Kf+LcYl@b+K(_*Rm(C0M9c;3`rEP`h1jn&NBtH-If=!C*wERM~>Pk*;A(q2m@p zBzIxtmxW)jsRdH~a`kn!$v<0q3tx`0$BSt4vi-L&Sm%-%dqH_S`-3g49Vo$RiHn79Bb+PIn`zW zAx6Kq76l1=;ViVe$xkLKjjYkH+3EX>1?b(Rs|&p=FdN}DL}|WnimdFI1gdF8=;}015IQ#garPbxe|5l& zREW7fK!=CzFMFtlB2@|BkcKNzxDYTdyD!fkz{-mJ`|g<1Xz_VnV7HO}JX{%{PhL@7 zP3$fk?ET#*GJm~yj&hwBH}>j#lCp5Uuf{R98h_C9{>Y}j{J@D5cqEZwd-D$XLh*3e zmJ;;b)%%lXUhBD>wT?M{xzYeN94GkUmnx5k@6gFOxv%JJw}m~kO$FE-axpo1yrzpSgKyUPOzrWR1!ZXj2Nl^HuLrJlBdaxMqPZ=|9+h5_ zZ)O@mb=Cgn|Gv!hg++em0LFqxgLwX1kqq)KLbo~L^Ee#_QWo6Sg`E+*okMMKY;ZWe zyws&TCwX!skS0i)#L3rpg@?O$HZxPBJv~h4BLD^lMk`#Tum`CO{aJ7=fqGhO9dnE$ zqKKSb-llrIFda!H9^IqAuhy=}dYG{@!5IN{lMo3THH@V280AIqyu(*3TLDd@Li~Yu zEIL=%kEkCRCF~D1>9V?!HRaUTDby~4x)66lbJgs>h7QA~{$HJ*JhbR&_{B4MtlDU9 zDx_Vz&{H|CYXdBmgVmxT?1HH1ezwY9)l?VdX^1E@Dw*{bQCl>6m34sDHvA ze%@8*w|{=-T{@5@Y8mvs0-=goIPEv?OfK!A0$Re*)RSp2(di1~$QemGtRjm@jG#dX zi(qD}1NdX69_FQT3@GKG!|k@udssbxKAyJYF+r)a&G*B1gLNfK9KHP3e90?O)u(a_ zeI2nxC`bIv^BjbV&N405;%?(8u;j$Z8!?+96`}i^t#^)uH#iZfvH;M%iKa?;Zlp6r4>J8T4$ zn5&);k>)ZPQSA?|6<(>1of4nUn~-NB}O{sbja7S|&&jA5PkNK9;iY)4Q`x8AepegilL}Uvz$?(juNZ>-l%>Y8EdF>ff;D#JTM%&MkcqjwW)dSkHWR%nFC1)&r(dD ztDs7k4q{ez+0A0E`{in4ElrS@WwO3Q{G+`ivr>^69nH_R>Enz)<>#I1_J5d$C<0*y z4s6)J%qr4MYTC>3DjY&4h1E{E_%Ny}ctli{8nd)1%he6d`YoQvPOO8wpTDnVEtOz+%J`pJZXbhnU=a zFA|w3S5WY#nk~jZ6o3PeG^NNsnGwBpKMR3N;FgQ2hZxQ_`r(wOa|q(EC{nRZq=^7| zdPFHyc>=6DC98Qq@|q}g@*(%H#Y=VH+hcZUg}m>p+R=D5@=hnE<14N4<~YM~iFqw{ zn;TRJVtG&OGKaK4!yK+<{rlMsbuv1|;``3Teg7P?KzEpd8@^oU@#b(VAh0k#|NOxE zaI5!DLWR%{74D?Mm!J_hnmmFnXu7^6 zk=x6V{q|a|TfTKY^dnx->u=G>bLjLIT@wGTS*{5SalT`F5Gfq*Dgf;lg2lZABezcR zo!hT7$%YzA#K{CF47&?SAy3GXC;)cp6;zCF^OgdurHj`tL^V!30fOA(@GNK}cqEEu zN~DbQw1ZUPn#t#2{o68l2Bie`b!}pzbib4mq6{@CIcTA&R3(Htu!M5)+XX-!=UW_K z1M_EC%iNpxKHq*v{A>nCqF-FTPzYOpBbD`^r& zS;*nyGDvCXTT^;-JYG&FNdzGwcKEm^HV$!xhg!YEPqE^^1Y*XWa{t>&;svz&7|l9^ zTFKg8fF~-v6pk%{NleC5OQ3d8iD^}-BmmU&Igj7?FX0n`0XGIMjXj31zJWNb^h2eC6q)AyQ) z9v*sZ7*nC@W{HYd-R1M~Cv0c>&JU50H`v&G55(9ZW`TK_hd9a2~)iY~>2(<_eeKIF&Q5Aa& z!e$taT#4;IKg)wUJBovvrR-Cx-_3#{SW>p<=0xPG>4fG{GfpW1%580cGkRScQJZVT zU}hU7V2*p+wS={;R}|U#@@Ho2CT=U6Y1aMI!)^v76y-2TY3mkZ;k_`OZreU_Q#iGF zC@4)V=E~_e^Z1|W_yl<7W>(nabu0*Iz~!RE8Yd9VYa)cV8ub#EMti^Q;|eH)J*ak{ znFrqfyS_VOXk=sLkOB>Y>syLcEUR(1L3j9HYm8Z<<>b|U~T zIRER}^PX9yuDgf~X99h87VKl0k$fgsveV%QG z#O*iQya)pQs+=~N8kkd8P%W3deW8qfiIjb{oVg!L4__FQ_`9EHRBggfAQH#NBY3P# zo7NO=;dk`=MAP}R;?v)q;~Km|7mK*tOz-k}3cqn;eA*qGSUmAif1YwSbDLz@1sQi* z%VQW<=?&`s2hg9F_WWP(chDr)bQmhD^euXApR_%!>7Y)QmM|3m5(YGxnO3QWig|*5^CKHt zELn#kat`8*gS+mFn#u1*QTjKSL+e)+`5canD;xjYi_idK_tfR`C!{gWUXhul&4ff6Qrrat5G4yJfZ+C76^V5%#?PlxhS_IzWKv|8 z?ZkmRV+^vlZFY9Mp*XT_sGN2%p3Sw~$~7LNOa$raHy8~HA z1%@tVz{R%W+f9$Ha;lA5A+CC9qr*6TnFQvCcQ_hZ(FA;RqLID_+w#Mv$YMp^0pkv~ z^qfUnLor$oBhgV->@sJ!+w5kLS$n7;FN7|X6gpVtY_SDjQRE$A31h>i)*(L^fiP)7 zl3aaNPyUNcY8iJIY#z~u5&M@EwB5WgEk=i(jdb&Y z>{0@E;2 z&YABvEEAzGhD>`udm0`_Z~@lNgG=5YP`4 z-_G`1IanhF=%0FV-ELWE4GrMN;>Z#_1ZA=ECXI4nV9Y7~O1L-@*vjY~!LhCUyKi-P zmg`z2!PZjnG|ZvGuqZ@9$bW`i%xLxk@enj?RVwzN1XZBv=X+V@?8XNp(C3~|Vrh1~ zaJfa`k zX~$&W#%^*+o1cIE75t|kxt8HVk~?+`u+fr4Kwueoi?wt1Q9nCNlyV3(@ji2#IDY(i zoZ3Puy1Kf!eecNL$gNoD*abu@A}2{D(0HN34^<+FR8lEzYrSG{X|G<bqg6otWktXrGGub$zhhrfbWijiG==^5(gz}G&G zTMx196ha8rZ{Ez=lcN`LbTwyAjk0mu7EIG1mCiCZF~PAXKh0IIy%)<#Fmv`Kr(gIY z>(*u{4DRF1=oC?O;icKxOrmS|_Q6d6M^AVp97!^1F*UQ|WtRgos~yz#5_%X5HSCfP z8+y^F=OA7|E+y(U0P6=wI9onJ(OV*86-ZlILKRZ+DgXGA0MXitw6^_7 zC4)%eM+y%E!?6f!RU+3#DMj(El67k=CZ+-wm*PRbE0^3+C?wC@@Ke)sgki|0 zEAIt0%8BQn!mX4k^bfLr*A9+6{uwHj6t0_Lcw~gDuHQ=-2Kc_e!sXI>CA@jAhm)|` zbM2L+vpv*mDHdiU&c5^ouDJD10FFQZ6t&_3HeGoyVHh$sJ$JzlQphLe+JXGl01HbY zwYp->kj>ouiXk^~86ZPD0P1Cc768^n3DdSA?X=uK1GN#zjr4B7$_VD&c@iQ`6l$ic zlZ;i)Fk6}8HADBT*va3$@Yg(7e3B_+oR^C)u|BhryM|uRZQXaWw?v7i%|~Q^1Xx`>JI#oX=D9 zJr--R^BjfYmL~j}BCew*m5Loetz!^uK%i)XSrDgaX;%D*x3HDwrFGl3g?@lgih)Xn z-s30uzcy~--`{l?uIr+r2(&^5J~E8=A%h@>&PcT!KvU~@156notI#BaAnXGeU05KS za3GUraXALjX=^w0BJI{uM;&$auU6*8;ZHZpz+py8+YJ|xny(0?gJ~Fql?uuaP=3vP z&9$4hIF5s81cXmbO);_LQ}qQ9Vy2P=b0w7LucXja0&QA&qf>FZ+(;pNTNy0qE2R0Y ze>_0GkR+M0@!XKG79azknb{J1HV?!nBf*zP>&T!{DkNTQfQH^Mz3BV&r)`tW~jdU3eJyQKKZC(oUqcjn*az<01}V5(G0d zPyX19LJ__pcg0MkW3{pO@mschE|I4vl9(aluVBu;)I72(gb&fLhp z-Wy`@b-G!sEl_bQ40QMN^z>tFJ+qyC>#ql3D7%)exhwhSiN8kyfeI-GMJB6bbmzKR zsLUf#S1OE$^!O4&Ys8u^thrkIVvv-Egt&Apn>bI~5dpqq)0<8+U#(H~y!gdRtv4EV z;|w8?4Zv!`pV@fa2*E&Oi1;}XHk`dEY?OZ!jsL}Y@yZWE^2r2xe4P5kB<}bG&ld8y zo)-rgM+)#`_b&v=Zgb*A%c8s|o z8M|*n;<+JS<=m;+AeF+KS|q6Zu}imD!kd^!HGZ@I%^lmhc5^SoDT~2`#oCm`x~>#M zgWbILy3M@##!a!a(dPKoN2iEv=Uf-i^YNCdM3zkugj9_#rl+TI90$WN$Y!%*@20*r zD)goDe8O54VH$+OpdM&~NE0gUD2=TfW9BLcu-%CPV0IqTDHGEaj5VfzEySk2-t2iB zy;`eNtGSG9-UDi$@uLS(QAGd9ChDazit{y;TK?#4$0iCRjvPG3u|p?Vm|Fw{iG+h` z8YGeqzUMPJHpSrsM>+cPF>J?*bGS7Wh9+kZKF7u@_acN~^3+kh>L??d_fV_3RBPwY z(m9kssI=>i^%Nn?@!QxW03*mrhx-qYG3K$V8%xVC`dGu@S1-k7U9Guxtx6w;N zCaF`SE^4^4MvXcP^#vjowO(IHc9A5>>FO!0tjXt(di$KOv$~w1}}X!8p5{sP^Bs))2OAD zE}&c}LNbX8LaHQLSXdyDNMKnOj^nU#xO?D<@g+-IP88MZ2qB21fgkxqN)svVD5cHi z7(jg?fB~Rf5p;K%_<^Qcjhdu5c%j74OG{-EnIZDs4mvC|J9-*`wcB=a=7mq=`zuqk zWU^^I*K2@W$kJkwrNttZavIYz89hCI&OX8*B$ZB5DOX#Mxvs^+*bC(Q23eY!WMN{I zp{;94WQJH=Dw9qnFVyf-fUUuwn+v#NM}i=fR4UNZ-5QLo%Wz{PE7O@I0gSmSrmrBE zgfsJv7wT>xpG{?{s1miHiWCM(D@_=cIK220w+-CK#=@4?n?G{$Ax70HEW=`#wTHXc z+~0aG2z~zBV;|;7?GOp=aAo)2ICd|ZZF~_Vr>iIU@Wa2&zrXq2*k=6k-Z*kAU!3|U z4psJ}%YsLbf1TIvxEp|Vg$-nM7bog3lQ0q#oL;=BMwIlM02r4C45C2KmJx$_OgBQ7 zJyh0dcTTNKIH#-oo(bRz0k(~88Z6b~v_nx44Yb2w)A?&n151g4#?%TKf!PEvsSqkc zMG6&0aY~%VrznLWh$3p97pKpW60H;y3k$qq=T4&2XDIdc^WUC)oPnNRq6SE66(N<5 z;jaON%|#ztsTN2#H-qJJC`#)AfO-(%g#o!lf^pM`Yt1xFa*v`3+=k)hhsyrA1`E2NkR;jpn+@M5Y0NCe>=S1%Re$GSpkhMc$ZYrMuj)Rs%Fj zngo$<0-&k2Zo*$P4`BNgaMOv29lffczt_O?6xEt)l1^_X?VR^4O64j&Yi|X$K()9; zWoZFBnZhswYLx(`R@Mqmr<2rHw;v!419^cd=6c;d2LQuRGIRQ62DjbC(##}t<7XM# zyq%u4*HWH)n;{KllVX1)n?qnHB&F z1UC-c$+Jt3P}Nm@71Ey^q~sUr%673>UNj_XP$5T|EyJchj8J2gS^(&9>6NVQeXrU7 z0PqEvwv7~mYU6u~R#~GB0OhJqYoalgil=~yV`C*CwM0ZQv}vu-TC^~9p;~3ItBW^X zeGNPN`p6gtzE&JsSYV6Rh^{Vv(WEBmgZ%j#o-QC=>- z$V_RPzHC2QYt|RGkRnT9)(L_T4V3)~hHW)nz;0kvFV+xdymDTaS4;z2t6=6LZhfnL zW1vT18zutq8s7_{wIkc!%pi98;y=_FO2qj)8`G|)j0@v6SL14};~Kw>?|HFW<%e&$ zk^B1kkW*7c6BFntB#q#GJFd7#Js_~uFt(Gk9+}KU^;$osSEMR7>&nb*8I_^8DC2?jL{@64&+4c|3{~N}V48-MWV% zjq?Cwg1{{z4Fj(h$9JalIb1KeR7Xhxgh5>Q)wX3@JbtUMU1~s%V@{V1srV252$D8L z8X6@78{mX8;#_?SjS?CyG}W+57$^qQ!>uK&!>)jf*|kX zTOL2Q<{c~Guc^BS@8ieU{9Am>!_T{X`p_qr$yS(bOYX+iE@i98@wsCyxE#u_WvO07 zV9=W$q88MsNA=d(iDs3PM*0_#c933pA?K9K`o1=#1Q=2@)?29N3(WQ@VA+5wlSVv) zjvYX=8F$xQ9jxM{%(@W+sH2GaQi*?e+iiS*5D-50DDF!y;h#E1cy^TF>{;rE4iU}H z&^tQHN8j>R9LpjM!?-+L!|5}kDBfRlAC3F1{Wp$lwOc7;XEg5TjjAnL2-LZ4(Sg5? zI_jvSZ^!{`8g-2y()g-84*qYJ3TXhK@H{WB4=UoCs<~VanajqbdUp~$1J(X>EG4p# zgqneB&(tLiWOwSKKiyw_X_Pm=Aq`Ud_0#z`56d9 zdV3-)%fc`Wq9~&7xP4lgR{`T;`nTJg*eNN?}TYP`VMjrzzH}+__^1 zw=EW_A3h9W7+>*-b6t70ut?^qr+M!kujSW1|9N_{nfO9T$MJrKj@`hf+t->!Xu5qO z4n1j~0yb7%yeh2_=gt^tI`w}$>ZqfRz9|5_EG;fADL^KZNy0FsTCEb6Bz`22(n19; zv`)**Xdgq$#;V?xqpxLK@pHD#>QF$-j)B*9?0C#>y}%|4J%o@gcxoQY zWm(FN_qj;!=*!}j6)2%}+<>jrA&mnC0v!^ns5QzrfkA6c!dhOmvf#}V7$JV>uW0(Z zUnOBC2((Wx10>AEg$dVm=u-on)u*T%HJ0j&EdWf*3{}5IJ*ctdEw%kk0!t)Wo7u>T zrK62&iik*u%@eg-pJf98QNb$(=jN%a#?~T7KZ+0{?jsEl^j53@)*3@LQo%Ih{+bIv zWaD{L3QQ$dIDkR)@X1&qx;G!{kVq$Jn4NYp?yJ-$NAQ}Vg z^4bRw($JF=lTpHPWHSwn)*5ORg3!Q7rqDrf&SDQEnLzvDc^2mw?YYV%9{=DyNxq|yZK?_(!0(=K7L(nw<4P+(&wlY|X-P5CvF$t0fV5d;AX3roI` zhHgTt5b*#lF4!h32H_R=n={#wf|W7q1VIp4mUZqltYH|SLqOo9;$kA9?;{P1xw$HV zUp(jaV`nGMnFh{e(#Q>KIDPW$Is3@vvvhYCIDKkm<&aF)A=TYQ7zP;4gx)&DFfKVI zAIAM4cAKI|BUd7>dX)!b6}M}MZg^w5ZN!gRFIEnqQ^lm*QH0rnSPET9Y2(bm=7Zs7lgGptL5^7a-(Ff$@sl zLZ1%+ZLRTw0Iea>I3_7XwcTQE(fhJ%ImV;dzE?wR8*f}sj?&vZ6Fl@n} zN+kF%iwis-g`|OB$mY1d0d)chj~wCd8*ku=W5-D~Er1JSZ89PEs8PDxCgWTITp+Q>aIgjg_OS^5ANm%^PpZ`97_?8{aO)v3#Z@+l|Ra zoB>&%^BO5)Fp90L=A(Y>uttrANqTwlfQs*z-E!+K2GRpWVMsmt|Fier0g@zVo%R!v zrYftdz3(3H?RqDz%6@IXnlP4vxb}7y$wu97Z4khmi#G-tB7b ztQ)iAUH43TS2kUIe`Hp5bx)7o*&Va*Bjr|ib(zel?8&Ep5%ETeW3$H^_qXRdI9WQ$ z=Z=4x=O*@Yc;et$cWmG2Ugj&a^x3_1xLtJSIvYPbK6kwF-o5$0#{H#Qi6hg8l48=9 zCL-ClAPVaTTWv(dDm~7{Nv=6hn=L)>!uowK2IKpLaZIb1tw+m~i^c%Lq8fXPzc&kG z@zR7X5x^>2Iywo5hZ}YJY!mZrUoT${d>q?m2KW#Lo%0$gA3?zCC?+<^7-8xYO_~Z( z+iF2Zb#v`MW6-K;W`|ajNy6&j*$(s7D)wRl4AQoUL;?jt5H4N-K@ls66)IBoh2K@u z-Kw-kIcc)sWWpoIPF6~#5|v7YN~J5RIC+|I#X!sDNIyP#1aWK)M_yqSK+#iqnas}mY-Scd0A@3`s9z~IOitD z$hG#8_0Igr{8~sRn?36XxEyXKi@(goj*JUYGQpC3TRK0XIF09J&vA-?!OR2Xa~fly zQjPHzmko@TNZ|RBtj5*c*gBc2ZRvCh!-4=taom`gQ=jY|r~SaAbEg_Fys=|5aSV}; zd2-^hh4V#Qym{kyFwZ>CR-WM}KK^5r{WDAIl>IV4_t~H3(b-4Yn%&782JT-pk>u&g zUD%F`rCc_3Zf)E@GCPbb| z^!E1B=2Wq4D;eya&tZ99@_l`)ravz%xj%c>ITG}DkTBTU2m_0{EPg`z20I+j8K%wIh$5L2YVQCd8rP7OwGMw23 z7p51WBvs2AX6GaFIgOVJTnsbQGs~~8(bAHqG?jGCwsv;oWU`cIrpUGqp;VdXwUz>o-}tjXiFwB*kj*+nn`(Ai-Vh6b%7 z3i(A337RC3bBIi=mI!p5wV_x|1TZa~V^9+SCWw<6z|EU67;V@y_H5&Y*LQ7XjkgXo zJUa6T!?PzFKl?9RznAVzFRESf&EOk++h4qqPdxQ+gmFl0VjemCO&<8icQS8Jv!QDP zceK8Y|G4q3jpv`59pQBOG&@^vCD|%wYB3p4pXHPQ`HLJefu5QGc%2DUJFB+m>>+(1hD@4YRQC@g(Y_M z67g%yuClBXNrLO4v|^%IB)53rX>ExFN&+Ydf^ZQDpaEqRL|UoP(kietxLTp25T!JB zx;liNE!3Xad*o!PRARnbrC2W0-``KSHH&R&tRO&VT`VtiW+GRsVz;$7C3IQr!GViE z8nuuBI_>Rf(j}#qyq|7sLsfk&%c48$)7#riu~?)QhCH!nUr>si87q?rpq2BI0qSvt zyC8rytyQR0{oH#0zXUL+8Ly zGC`#rFZha_~Lw#OvXbgMN3NygM&kC-m;bT8#dD3-pTeIJ6X4GJ>5M$xM^3h zZD*(~S>A16pbxjDhl$}tj=EQ@PNK@GX*$}MU$)K|L#bFZ5zHq0Zc(YmI8IDUq2YP{ z1ze1qC3=xS$2kWxS51tzHCq?JaRB2lqs!&Frir_vZ_4?L6nqG$}Jk&a3K=Y z+-?m41jzV4r|0Kr^Snkku(7N|%{6(JN|t7Em#|JnO{HV`vbN2m!^2ozT@7i}K>L9M z{L5S4%Fn(2_5AT$-oiVwStu44$>kHpVj`kx1%Z0PSFiokoJKB{)Os?hAdXz;D8NvA z2emLHEEZ{97}5}@ZQw8YqeBn`LAY=MBvy(@DFREYnyodi1y&ql4A^PclI^wC#)@Y2 z#L3~XSgBAdmkEM^!NEb=oeGw1WBEQ#p)L8kX;bAgw(DW{c4K9;ID8~rAhtq4p=C8`jb zr06le0SIDrV*0%;Q1S_FMbwdPYPUrab0OWoHK0=eo1`TO8JV5Mu`PNE$?s}x+lT6P zWtJvux>>@Oq;vH@a~!2OIy=MuzP?3c^y2YxIv@HbZyBH9&gb?MJ^eIR7&cNw)7#5O z_U@%MlWB|rR88-wNgLZSF+tNM%wTB*^o}Zhe9EQx!&$D*z zTDsK)wqs+Js<@r4*!di`V=vnD^f;NGZn9g~Vfz)VQi)GLdW2mEM|phz>0~=F%9F>Z zc;e9b!hPws>)Xl^ItwGOCV=K;hpKO00x;TsN*sRKz*t~f&b8~Z4e4kRK z!k54K&4rD={lq zBL@^an?+lz#mMP^_O?ZiS7~aG=sZc*Vvzx& zjvQe|!)ygo0W_#tU@CdEYA((T2ozd-k#{L0;V?PDZQ)rm9ePJ>yUY`g=HdXomKvjIwfUy5nvh{p7!J;a#U$toG zzP0y1@}<3BWORO%zLq{JeuW?W+jsDE?Frm|i=7=e@e_CbRO9h}=<~tH{{%ckY=Met zEUs-=8UmQuc6$yAS$Og!L0jf*?RKuN%;rBn>g_fUNeJr}=Q%Mm!>Y~>+H)Q=1oAVGlb)17arr-IIc~`wsBo+ z@%OkWq?+5yzb3Dn_Jc&qzy^0~#28R*2Co5yi%R=HE`+_{rVr9v^Cxbo>wePJZi z-albw3jqqUJw3@pms*8_qsZ7A*Va|X(iN?hzc2>yj0Dh6FW!xKue&Se$Z?;}cAMUw zWQ^Ec)qi~7bE8DdR86)lO+Mew%+r4aBoi{$-f%0%7>@5d1le|qbH^wYI`F(a#u&!O zPqSvtmZn!xX9(b$wOcqfl9Vh7!-&qVeu~9oRKixKPoKi|a%_Ehl5)*F^M3OAcFwkB z-Q0YYlf%snJ-4zme0__Dr{jYBul&G&X)jI)8{2G(&b@JOeKYq`|91m z`Y8a*R}1~hN)yM)devkU2dew{i?4rh;co=n<4^DWO9rwl(4Fw9*?;GafAKng`k#J+ zU;MY9qsQsxwLPyVYc1~b{?`6CajG=J+y3U;`MH1o8D96N_wmWuf5Y$g+1Yn9fA-41 zBx^4`=Pw@mAp8BjkX4K70vQ8#k^sgL`e^{QvJ+xMJUUC*vuLtSStadoG3~Y>fN9Lu zQLV9W^faF1vZ^zgRbI?yAJh;n5#}QXlpn2>`A`%xno3|j z^(!00SEGm@_kDhU|9;xtwCFgA{Kc_Z^gc;9vugaK)Vv%_{V{=UKNe|S$!9Wb?(gH& z+&tFwH2n+GSpkYHv|A|hCkTRY2?9tm1~AZC`HrP4uC1#XTT^fpR;>bPvOPU0t+28! zezt4HL=6Diqn!Klh5LKE>13!eBV|eGuVT-aRr&y9O~3~GOIWUu%_qmR`(_n zm~rve4q#QPI3}jcDYM#}XWhDWOixdvJdcwnhogs{Ikq>`F*v8R9Xo{rnXWG4T0k}q zXw6z=9gB>ui1ovl&xW43HaQl3f_9~_@7&L2EH zzH9;Fp}}58imRZMj8)rs>&xgGT18N+GIDgBiiw$-+Q+T8{s*>fy_M_vS=z^-($XQtEqh!_7zas`Uhhw2O^uX90zNZORv^9&&1&w7hXC{CZU@rZhfjB0b zm|(nA@a_l*MiuQ6k`Q&UrH*|LSg#1mvp87qphW=nWmhVV8GVEF-7xw??nSsH6*9(8;S zOBpf)9e68y@P<0c_qCE6?8IByO=e{`8P7$HPNBx8aSV;uu!0b4wv4y7m;9zd91T{n zg69~zqET+U?KY;TrwIU~6o3DZA3N=KtsZd;-DOD9KRaI_m@Cq1MdVzItfO&lJ?~hm zqLivBMW_~c%f(9su$XLy6+_V89&r3bz~+rvI@)c3xKs}B`UQfOiSfiE#W6Eb!pnf1H08yJqtvv&W#!)Le zp{J!Tfe!*WRf`ytt_vLF>MV|x!Opsry&~`W#~-F#TNrP-wR1cF-&`XT09@K`=aU$-Bz-OdGmtEr+*T~{^vDQ3 zEd|#1BwhMbUiOPdQCTX1YMCTX0jp|0Im@CJ_>0a_M{8QNrm8f1P<#z|48@pIcj+UVs?@EEqZRvC*wI}R(4=jYdDssFFeW1whmAz6eyR=WLjIRvmUp;{!I+5+eGNs7(RG}saegz zZhr;c-7C54&ih%jW+$$j$8{Blk9?hdhj%f2ayseu&3fGY zn)_L?c?ZM+Q;)xwO!v#lX5F)%7|-q==IF`k2Mq+REfzQ3kYnUjKuf`A(}qU+=cgjG zXh1&aFJ}@oC8&+Xo&CWU;zMJg6>3wG0)|+R19OhAamyC50Y3_<1XZFa#}Z-LN8={W~>}zp}0Q?dH_t zuJa3Nw|Y15f&ixWv?>gl9XZ8VvB>RfR@3Tb3AL`wJMI@ai*T_dm2-|9=6B!tEmXpg znM#HEYL)p~jiT>U3Pb!T#KaLQjv$T*qli)%QVas-Yc=MpRc0#{rYaR)vw1VG2_w{! zlzQ1eLV-xBsR_^f3c%*RKDt{9JUuc(+x$FD6)>lo&bNj*i~R|LAe_ksOaf7{!h{-p z+tQVct>?3@RnECquG7;@7E740joi=><&hD>QYrSj*UZdJ4e$HR=f5)a=I{9SZnwXm z`9p{3?CfOK^dU}+?!tM+8;MWNU|9-xT{q#_9PwQB+&gPbB8y>+t2Mai@K;-7ujqs* zCO$Muw!ee6;^S=Sj9Ig04RdpI6uP^KgTVaBAOGdP{J^G@ZcA?&!0YQL)6t1PTcnGC zHqXX$Ej&lhI7t_9RVme6)};AD94#X-ePHYz+Y|>6S2;24bIVORo;z4$dM5M(_`)~7 zdFV~OJuM6kohct}t$8Mbms5K3e~`c7=dhg?Zn)?5bPcZL@KcX5KRw0#G|c7;OqF(H zsa<3pud#B2wru>+rxr!jsxfnula1FNShtCdx4sOor4_Be5e*RT-x1PQ5^Xbu9 zcJCXR9iOj!4Pf(zES>E(|NihS>(_-i3uW-8!4#JW;Q6k{jRa6Z*(B{(1+xD7E~ukOB=>0r9itqbty&;A*kGh4WE;6{G=lfTH9=01h6b0Wj2oTGI_rpQO^2CG2n17Mxp7WG)~9tjlvPJ@;l)DeBAt z9rJTMcKify*t(UQSFYqM`wuYYWgjVo;bu3EH!dfAi$0jSd2TvG zaFDqJ2e7@iT7GEj$b-AT`oxxvPrZ8Q-7nAh1B1*RJIbmxYcM6l=+h73w68|Fc{Gq6 z>>%z82v5zPeP?Y=&UJ_~5pi(#wP|%n4!g5JJXax{EI}O8I`cFuR~5K%Xd|<;v$S+| z(bdtxFaO$aj!&Dm-R-^WC$*D_?0lZW>eU#du#0naWg+j{ zlJ3k~?X^pnf@|uEGjpJ(fL_OewQC|C-Bsqz-`dViJ3YSiwRvio$EIg1H$L+CvDNqF zGIVsDxvEEZR|j*m_u}t*FCE*yAM$G%+O&Op% zR&Bk3*6wtSU+DDhlX5OsIi+<9A`6T?2XU1j^$ zMM5&$Br@ll$x2g-8ZJq)rhx%~>dH2}Cyt}mbfa!qf%)=tL|9L2%398u^b{3B~^z_vdgxz8ORMX zTb^tD_LTBve)!8jh^}g^f`V>^agw7n>8xLXws{9-6bAKlj6Q~Kp>AIT)qwEG7`0pb zo7-U~J?;x_H%yw=b7uGX6p9WEYJC{-#KrYRmfVI zZcj5?n#Z&jD6C#hb$kqeX4YgohUN<^b{zS;kA9)!rw96P>EFEBnszr)t@*5JsbcTh z!|>5zyp=a#XIH>@kxWMpYug~ve6=BNO9imtT12i*oLzD~)EZrIvAYToM1&JX;%Y!f z*RZGdv$iE<=g`fN&(odH)7R6(U;NF7OAkGB{IQNrcb~L#9aR(*RdDhNTvO%p(trhxUaSo5jCbb+yM+@Uyjyvo5tHEz8r$AQB& zP7eFjFdy5qcjQOf+C2B}yVjG*ocYnTwzX2rzLwEv{(;`k7`6VVu$?R`x9nu)mYvK^ zj4^e3n7PR@D)aM%ehp&`+Oo*x@)X)TY407Nqi+D$OC>X^Vh+8Ju_;ZV|FvW?XHUR_ zAmYJ?4sqnf)Du4J2e|!~JcYdGGhdwJ#+_lh{F_NH$Yz%1yD`mq{@`e|pMrUlT-dt+ zx3;B+%E>u$`%a;@4`B|C!-**(tber$e}cn z9OZ&G{I{pxjWN*Sbg-p$D^uYVr~DC=Qq&@!DwT9fY-&DvP%A(O25f~=Y4R5*rC*GJ zwpo`<%>tMWu|5I7h91f4i|#{sEH=8C>*6&41mPC?XggB_10?Yu%{L*F1J_ zsm(X9kr*43tlxYN`)_`~dCPv}r00Dd;O3PpS>MymL&uJhJ$0J33;#ZZBunbev1Ht& z5&07YL0A^+*M9BS7TqyCxi~>m3YB)!Xakl~*s;Me1~-aKOB5TbwSbu_WV$*~wx%{Y z2}Z?srr`U2&428{FK2Gwwy|sVrj5$?Ys?%vL~Cm+Z7!VJ{UF&~o?OQOmLH-kK3;o{ zTyHCxLKfS#aBT}WA+8PrS}HCw?3+~NrA|2*5* z4zO?jRaQEg1*{bDp#FoU?b=+s)&?9<4p6Wxh1Q10cEzk;>(STa zaOg;lT42fwHFfIb^mf;^85(RyYqd-YYT>o5Wo$aejQk63a1_w zSg~mvtG3?2s%8>vBq#SwOYuo zr%v#VhYz2g4Z;rtX6vRbuYN@fPwlQ?Stag$Rpas<0wcgU3xo2TyD}U6W@hbjZP#3V z#7Q?7XaR^Fjr+`L^vX`uP&?-6B*u>_z_i9}&jc1VCnnS;?G8@&N`bM`SF*vRBM6KE zOWVZ67?nIHieiWrVH{Bmi-abk5?9W&9IYCkFsezxQu*`BHmyYmAP%uUY|s;Q7tpWS z2GeEy{Ua1_8NhgrMEf)_rV{C`Pi8oyEAt0_{|L)8oLX}JHJ^idz-a+W)hherh#doi zbmnpl&&)7y;*ziR(atd3X(g*JFRBArUpZva4B`6naOqaB?N{H-GFzP1{A+5aGq(Eu zbC&h&{(SypfZ5d7%d0nT;>h$g2lnk_W3kkn{+$L!NxHk|mJ#PO82II1mVf;PK@b5v zmjE^{C<=v9+N6sG#Kt(0p%BH!QN$EWHELFdOlJqNU&Ei8M%$U#@>(n9a;f^r*S?h5 zv2JDO+SRL-+tx;9ZVuORSh;c~Gbi>D%unDITFB;G(X{|oso~ld*}O}pJx8WBOTHyT zS9=cQxu|@GOiPwb*1^W0=BlVt4I8kd5}e+RGro`8Z@-Ra~Z2e*t{PBwB{TjV04^8yT(A9OK0AtE$5uhXROhTt*0%m z<}IZvN~u68;#=*t@v`l;SOTq709ydNyGt=O9dYQ0;-;NBv{oEGS|frn3uT`^HM3f4 z&B_&>%YJA|De{FbbbcdKlarX!pTL>=G!Ub77AzM`1S%D}xCSPK>L_OVn{f31P#S)i z*=h&*zPl;3cAs^&Z(aVLeEI~R|I)s>QXKtd4Ap^thx=dG&fI*=?!9x|d0R;PLI>g~ znEC~Io^#Z)TSfrSXg{?eF$KVh+p?(H3hu$lWD-TjhNF`h)L8P@idmDZ+4y!Mfh>u% zj9DCQ89*DI3^q%bc8;T%Vr`yMP$EJ%ABA>}HGBd**%oQzbPe&MTbii9AfGn;PsLp)P<}rIL9TRaz5_pa+0w!$x zYkTwge*?_wu1;RRbsICaDi817!^+7idKTV%CjDb$GW}!Yg2w-e01AR20(b!en7Dyb zsvZU?EMt^qjIm=wdlVVsFl4sqqw)pZwl>02k+4)kJK4zb+A5_|x%{=yf5zIec4g;| z?b~(ViWMlOFk#55RjX)m43h_U;ZL0;qa(6~R%~sfg9u#<(6s<7HniFrzZ?*jtLSQg z4#K3YOzgw-ajM6jBs}&6>jyg7v112?LVl`o$yvICc~-VLbQN6MbIxpQ);^VWtx4O`vs$T2Q~DR3CH*^_ z1lm9wD0+L~;GvLe)#9cd9_32RsnLKC4y(xIM^DcURjL7NS9hIN&a_r|g;5r9A~DTfz{_5c&yfH&_bOUV zNme^R*ptUPK7~_`P&{H#&?vL;n~=VMF$NVY;&`F^w{t2}PyUF}pN+5{K`GSB*Q2%$!h?q>Weue} zSJrnY28NeO|CSZ!a|obXrX3eVP*DJA4MR?pO3XVhHw+F^$Ywb;JIlN=KV|OFt9x;HbQDjL zRns^ZZRAwD-k!3Rl3hE=svz4ZdTs`vtv#Gbv*M2CC8n;ek~*tu25DG7)+rPGuDgZuWR}q9MSKLdb=U3VACgLYkno7$ff$p%GQtGxcd>`nmcG`H zA<}GbhFnm$Sud20AOSyN;x+spziK8Wb%vgx5MS>*Bl7I+%-i6aYSR-$Q(dTWy=@PN zZO=xXiSv9VW=18@8PrNgl0iJs%!2dZMrtP8$u;M}=4>nN>8Zq(*6V0u3}T0d@+968 z{kE%G8oyRELpKk}2ek+;6FQTT$V?0Rs8hN?h0emz14TW8P0GE+!pdq6>t2jOUu1^J zu78La??ZK9(z>&i1$!SX=z`8M`eWuj<=+36C1~&NGZMX0h<>B=u-0W-`f*J32fa}x z{8zO5V>B2(oEyw~lG5h$C0bIYm3%$!m#U~Hf0?N@`$4mbb{F(lQ4@`uTjmW+BB+0F z;bo#u2ZeC}MjHPyz@?d4NE)^p4ilStA!RSd$4Ub3`86!`=@M&DiXng(RB-7%+fMGZ zC<&)`bL+JT1*><2bMDP6Z2v_ghm~y6QTNIjM^`5XNIdb*su$+Z;=(|sY517;tclX9 z;n=YttlG#C{h{ysyIodxuTyhqi=h<@`u_-p6#DxH#V`KRZkGEWpUz^FPj3UKz@^{9 z!k!c$AX$J`J{}(YfCBqcQBRIbT_O^rmjM#-g{v1Dy6d|)y%ThG`ub2u!Fub{aNI-w zl7b??y*+2DM2km2KvqkOB-!j(>+xi4rPqJY0ylc9#lQ}BAdm_(;J0fuv^3+Xv7h@e zFy|JM1n1%XHOWxXs6;{Q4`|3G%;lxeTbQ=obh#!`QYqYvBGb_FYV?(HnA5}&Gbo5+ z#od)DG1Bww_SG?%k*S@v8l=Pc@bh*Dal4P+DaAo%v&sW z)CQ;5lBIvVypa~uR2V`DOWe>!aICdW>Y9GkasQGkeN~a1qnI%$t(1(b%CPvcZ>IKa z`}{UhErzh7jg1UN*W9j&fyXofow^$jCdmbT2m=~BB2rKl);WZ%Dcy&NhThDpAkyv* zPS$V?>qo=!d6BV+3-TkHR=xXkDaa?@n-AS1B{epaVf?iD!ey%XrCVk&Px85~0-=X# z^p37FT#8Sy3w?m$B%9?|rxI`3$`-cQzh!;A z-=6cZpD$n^utrm^)indk45$@-0Bh1l(yR$EWDKp{inSf)xv90YrwoiipJk6t5SL8N-TQ@HjRLBmB)K%5AJ|=_I&sh+qdQX>2a#wT9jQh=ETjObGNgh7auUijw%EVRq zn1)z?Fa20OjtjLtvnjWU7{Vyo=}t)w(osf9!7y%x@xwjV*ooH&XWUC`l(4)rvSH;k zs*mMeG@wXLT`AhWnBWooa}&CO8~+-maQw_6EcE3BZ+zKu>S^LoW24%S|LpLVckt?c z>y{sg_mbk#+&w4 zq}cuWHlawFVxKKb?2UGoNZT%W`C@L$!RIssqrCBwN;qYJ_k-gYR!7aABxzWelOmy1 zpTK()G6f|iW##mMtBt~rfV(4c<$Yn_n~Le`3(qo#PRlx%?#v`+Bqp=WI?cIy+dt%_ zG;Fss3F}x*5qEC%2JI7eI=3H&Yh?`dl=O6mm_aPMs==lwGWQ5BIKcVB<8}eb>U)+T z(Vr-45x+Qsd@jrzZp-+*o9x;iKK_vLNILQh{%T9?R*%hj`0uZvWH4o^!D9Cu?_y1j zY0jnG8)2>0nM%1>ij0lP9UTUSC`Oyq5fn#4V@t>;?`6%K(QUxfQ@E1&(R>*BZ{OXV`+xQT3^qLe|R~wd~RtVnc`}D4T7mBT0??$^$ z6sW7~8xhe?fRP++or{ligCzt62vPLBb1iL#Q`@45AaHj&VBDCQi-}%}%a1@mo+_O> zoHG|#zs66ZxGaG`Ge2lcGczn8shb<+hL`1DptPUN_x}aCQe@yJdQE~VWB$a%^ht4r zzKWe^^`HDyEEUYNY3x|M!J~5`C`Qg>wdv^HEb+3RQRPj*72boQ+MXbeA1jlxSqXuR z@W8sv&He0z-`u3P;cdE4)6(7ka&q%&0XY~O1}y^7Xg^W`-Nud6G5a3|Gwfly%Mc#zzAgB#a%on6sev! zyG_>Qv-?}&5s*|KQ2lqt^P@+?d*X94OnYl)Q#T_cOi@wr*?Gn$n7sJ z7BQY`A_m5&=$H{6z%;u0@T2j1R~;^={Bt&P1zUG4nCh~v3K_hjV3gB)+TU_>kXlz4 zb~nWNquu+fn?$$g$m_tNeTyHidfrNM#s&ylQ`DKW{K~5k!hIHQ@6K_gDry^hR8PUi^;fkZTU$X_G3m<{fWKw2ppo4nMc_ z9;~P$xGz>3{SnL<`$<$(%1RISA-zYQ^K*PE--d&E#9fvP#XK_FD>iip;Ovt9os2UM zH=OI_@@9x;bWPoOt2I%5skYpblfYZC;ZL26FVoWKt&4|d@ulowUyXefC_G5k8kWOs zp{WNqBPK_z@=BA5=_Qt;qSiX!aD<0{y?H5~A>^EVz9_oT;EcR)7;C~aA>w}ZW@&~L zR>F&cY4P4Kevk=szn1A*Ve{~-<^vu)A(8~r(Hat7e3|h8-HX(SnB%pX8l+0A@+(!3 zB4X@8&98rU)FA487M>iYY{SMvLQWV|f9}}2O?r0+de~q5G4>ZZBw^IMo1LJPaH`@d z9jxt^7@FvB;9qXwfeF>snh#m~JU#?VRH|cK?u)ByB=76lm)UO56)q+p$kl@#pmsZH z9=c5fb<=CCcD-=+KIEZOHb6nLh&lu71fCjo^Ot8>_h1gn>z?T4)l8chvrLBT;B>Wq zR5Fvt-54h-_>k_}8U6UO1_U_|ecay<=IA1hXjIE)6HCe4v3e&!9w)Atn(1X5ORa7b z4f0vTZ><@5JN6Bp*gJg?WST0|VrZA8ylFmPq4ni>e!19Ap5V2O za>cNhgjgJ0$6DEnd4#=9JcQ`n_pczAr2hy~c1BQ2IjVw5wn(g(J5uCS6B;qw+CE0L z+-ImuGH)d!Yfr>*(}J<_$8TRImq=TuzticsZhREh`st1(G21KR86FwSv^X;@vc)Nz zpEgE+Qtvvrq0`L8`4Nts=Q3lsUC|q-Zj?0s9rdW*V`4u9zxQ)nNkT2FRu#BBC)&)( z+C6!(P??KcxYM=Bx9{MlveXf(i;(Ix?tYi(N8M}{uZ}7Tj`C~k{pMhIF>P*=`jU`rCOI}@8L8)#c#4DAh`$aD$q*@ ze*u~q&VvNqga%lRG>w0btX|3Gpi(nC?}ez4ruVEi{#GI`ovu)(H}D~OkJmXy8jG4L z`dLjHF|bTIgS^gXp@!$18MC{nfw^mG*991!e_1;~J#XFvX;7dqwS9AgQ)n6a8Ue_x z*q=_0Mc<>{8LokMon@?t5nhjB+-zx7l%a01q%y{u#45i1P?3#cy>>2y|Az{qnwq^8 zg7-V!RIt4`$SGKi@E0!cxL9Bvg|#H^Zcoy8m(Pz(tJ$CBC6QV9alh<^$!h8_U8<=l zrt~j+X+1Q&dvYgXa>lLLdI>Jy?SE1`!VZPXjOh}7EsXt%41(voJR4v2y88V0-<=3! zK_O{YMxJ(wYVkGDt`_u|J(JwyqVHU$kdb2cyEQn8lG1g<`9qJRuX&hgVFGAXXgjJj zmS$l~Ma(L%vS8A|UQW$>?1b?-gU1RXRg6=vE?L(2b-0oZd$=&5pLmQgQOyT}__ff} zijXonq!p!b{M(QV!9->f+L?viLh@#|iH`o+6~0^IgA5q16qBU_XY3|lKvpU zLKzq! z`f1VKRANV=74&c%$ZSG0mQ2rxhhSlv%#8vzF45OzR3*<&~vW_YA8z!mCs zN1BvbP*qvdI8dLRnvKAqPBV0Va1s^Y9z_VLexftX%2>vkY8=~@xBa%^t7d} zk9km4t?KkxOXKDBSzpF|~#H%?f=5p;gAqDYYt7i|Sb zcGBYwZ;Gs~s8^3_+A4;3N&3Fy{MS>^d{|(z1wq*co^>7X8~o=YSvzZt0P`?o`{dtS z1gK(8cx<;L&Eptm^On8c{S5$lO@)M=goP?jk!#EdH2m(;yqx_baDaMD#$)NVRtjC5 zOs0DijnTZ>wP3kkO_yY~({ps{?S%FyJcx^&v7fQO@NaJqeV=>ggil9j_T3Q#I0ji% z{I-{t4%MkyQ39?tJrBVez=b69t=xR#MdUTFbRdT{NfL*A+T!J&3PQOFqc2rJv7(P& z40}dy4a7zAfriY$$=o_E>O`tt zR-yPYrwOyc2HAXRXh6J@a> zPQu98`1pGn4iy_dg(bI2_Lw9p54>*R24a`tck1ll+%IOYQaXpXN6WHIHG)*sOYoirpF3sWD~K70F1BRuZ#OA<_2{f$cI+LnmT2 zPj!oOp~dOZ*R%pTcLw=z*$Q7;&erBJinGl@%!bZfqHbgtlpnEh=Pk27&u@L06H)mD z?p7T75UmoTsPb)aSSqofs}i1oJWLh9GgoxO^k-I|@9DrUmB7^#`D0A*4@(VpbD(D}*qTU5g) zp3P50O^^3l@KrcnPBZ~YaG#C|ilQb$ad~i9Oc)KCUkY2LM&hoYI(mM!bk5d|lC-OM zXXi)4P;IHS>6~yi)!aYAFhs(}lkzGsW?859O<9#7c41+ zN-V*?Oo_uJ>9mYD&8@UA8f>AjH(~{j)Kpt9FMt?vZyjcmqycisJi>}9b$J1lR`8~n zgF9`!t3pzMFClEU@`cu-OUQ(~5XTX|`)vBZbnLR!@9NXWRDaC|=fmS&V zIg{$VZxaD12cijnYpdVRbWGcNq)eBQX4Uj2C4-~?e722*J^(=FKyA)MV!;-$KRCV` z6e)5>u4NMNG|-+3OlV|UhnUU(J|O-#2#Vhh%p(|!S~u-7We>b&QB2|@IQ_uDaAbQo z%=X8a_0LDx_&wHydj?X$)R$jHl?}s2u9f@l5ePGxD7$8+LKAe8*9GboN%>0iaJTwC zI-HleI&BE&FLr3{;u_Cd(rx5#`xUwzelUqs|F@xJQHR8F<25SPZ$=tbQOu&lW|)Xr zB!4EJu-gGS3H@c1BNmjRS-5K#@_g2SIbF6k@47+5;;+aXomviM`ley+5}B?VVo3vv zNMf*WvbMyU>(XXmP>3$U$~OCJMi?3`1$8>60J2Q`8i})Ql0Gs=rqoM_C4O^BuM1&JE9E7j-9hj|x#}oao4Brh6@4;3Pe^x0zCNn52sirPKR}oY ziWqb*TE?6*w6GDc-neyDMMp^5)0?Hc6&~og;={%(wPnVj|D4W7nq5}unoSNGHDw<)H~OxWm~#f7 zUF`99e$J)7H`{d>VR6qim4b4{jct|-no(l56=mPNw5iNsv!e0gsCeGaO*qDy4$mHUsymwLhA5s#0@ z@kk|TiIZP;^jLU@tgHs7Uh|wwy!s(@N@06IWxurBNt{_Q-*mS_pQBpyVKBI0r0_Z} zqQc7Nq4Ry03V;O`5{MMZR+u6^4XKsc`{L4I$AP6a1zDpdMirRR;0^9Gt*4X#_Osll=%HP6uPURnfgUM6Q!X2 zy3995O7Bg^AKx;5weI8Mk0a4P(BuaNMDk4RTlQHHuut&Ce3)hf?lc4STgu?!_38ME z^sS;JU+i!PN$4=KVb^g9B&#Xgt~T^E?7VPMrYNjO5$5aR`x(O(<0`>S#2Q|s_Cpg% zx9A=0Omj6avHbPN$al;{ztxT7K@0Kth6!|_NcN*$_SKJ$LVO1;?|IuqMu zlQU7DfN|n0dR|dmBEAhQ@Q0SUnj8)w6IJ; znA;dw*RmdD*UP=LHcrT@FMXBlerjl=W|AKAoqk`H8h@6}clW)aO`lEV5s8B1V3gv)|92Gw}`ee(9P4 zNc#aUN2{sg0~*j#R^29HH-&o>K*`kOQv>wb8OR zELOXWUq3ME!(iE5Qjs-516E37bTepS_^|fG%Zi0nIl(j=BAdQSJzZl4KF=2CID#Zo z3Xk3>w(e3>gv=R_r1%VP`Y&51+vb)R*h4v6F*{x`PFZYlA+ zB}b>;XIUZ_GTr$(D!3*3CpQ{^*wO9;b{`z< z@Ne&+ZG|y^9cdX?zjDs!{|2V?@bxDc5z zjh@_`2J0cRs@Xji_;RBE1DDSeoHEdA`LGrpn&h;SXJ@GQKF9nlfEJ^d_d3g%1($o622SH+$wcwcSwzln7 zMDlw3%`sGJ-*&F8dy*qZw?-WOmnIwQB!;%|z7ER}h>B8l48GLZ5G3JwEgiLVfm-1M z41wdwY%Mb_qA4Sflgaz@<^N_-pOEXxOltrk`8(fsDKp+qG}w`YiD^{M-?M<&f~EaA z+6vJ;Fc^{t;TOC4Audh_mW@-}<*Ywgh^S*j(JD1|_PzVY(9@%g*v>LU`-B;qKrN!O zb>la5j}8lE2vij{57%xsnvSPK_3?JFFB)30m;PI%Mk3~8g7q0g$NozPk;KCm?3xTy{d`Xqi1i=>jR(j#RYd5I}%sRt>o=hoE>G$4iWfn!Zvnn zxY=u>$6|G5JK$kuEJ6G+Yxyzn@a9|lLxQ+JdbW+j2noiaGNuuqqkc+^UVYVNng!K! z&=xPmMjZ}Sv()hH{@>pS4G5wxEa#9?`%i0mOH}LyUl@w_bqVexCZh^Pp&Cb!+QR9L z!{agpwe2n~&d`lH4b~JW=Lfy(vEn_7T0UkkU-MaZWNp9gGr8NP7U^BIp?J7Aj!hSr zlVPC2ITa}G$l25TlL7TZWxb7aT>BO9kay^{9fy0jpYyoN*&Z^?L*n_$;AShD`T`e+ z+k1ENQdvn+1o1BRPWNdyc3=)*3Za`i`<}@x+Fr~g+sy|&YzJ&HUNt|SiY+}DIG7!} zpdJT*=MR{N{jIMVn-K4^F?6ApEP>v)>-5?;O_e)#9% z9|QDNzlt!ra(g&jeh_y*6ozcKow-phpWAZ(po#T5DO$9hs|W)!+z1kH@}^sN#2;@o z=mTf5W);n+G8gY3I-2IMb{rOENyCsNAk_ZTEK8TI8G@oZYuMy(i;2}v^tk*(iln-J zZ8a>96y~HGvsthID}L;%*}Z9{_PXS>^+wM$ap?D68Y!J`I9}L?d6h0!z^@ekAH)*y zrHKlMYPyeWlc&)X@f3@53@$COA5y#-wS-U{Z{&U zZ7l6+Wk>oDKHFM=Q$p8BMNzNM@Px96oWFcJLn*<_CCK|2t)h5bsp3xsek;#x+v|0}zI;lnB|?AN zvd4;xx;WT_9FBNFkwM27X>|M7aOrdtK5~lU%8ABzO8xGR4xTRj_1naM`J&s7kL-vo zm-`-S6JCHkw<(`6Dz=MVzf;rQyZ+iof|1V?8X)~(@B)A|gd}W$MKjdb-oO?s^nLc9 zAVWpl-IK0c@hkqjv7CFN>S~@;0p%{vSaK6M7>$4kcgIy1q4-Jc;Z_*A{VOa=9cF{pj5#OQJB{hEd49B_O49D#kH09+gDW8_BCet{_-3&j{|K4I1w9w_73 z)if`TbfAbTTCMbHiV|E7{`-!QvEIsqQ=;YSVP>U=2zs#HB~#YQ@LDi!WvHvr{%DACFYqj*=Wk=f?YeD`z|v7wCN8P(n53 z>fLFAx$2i{5KXYk)<>aB5@Oq}SXZ5_vmdj!YsufLOlvyn9r_#2y9JhGUryK$nasYf z=8a=g{t!1x$4*Wj4nwsLkLkh9>#>nmh94Pr*Z;OXg$U!f)2-WD4jrGEmXWd8&L}J_ zSVF%0aaa5-AUD^!J>a*sSV2rltWO9E{o?PREf7oAx13uUP=p0dco!(Z2i!Tvm*SFV z_HF`7*tq~KHQ+Uy#-{Pb?6m%y=4dwW42$vGe<%dM)UkBwGr+`cW%U(mNGt=Aw+wJs z2`Y!{SEfmsDOs)ZBiJrQdNz9V89p~R*_SxB3r$3z$y?4Nzh~p8;T?wqLh49u9^sUA z43r4jnl~q+PcBjICoe-J$sSD>a*MWLJj@d>B&M07_s?mWul$x-wTzJ44+4y0%^;Ob zidSl*_9_HY#649I`79y6h&vq&wyXtfDN~E&^`+_d zhsZ<8wvQ{>)2+(>3Qth1a=YjdKzzmc5dk^Yc>nG1c1tM0z$9RN->^G+kKEd|W5yih zm2$B=&P+1Oyze6h$BBcdEi(1BgA553wYh6Gs?`|2|86O9?(A`Md_7{c%EhFi?0Nc_ zo7Rao^j1H?WG}S)FHXZ7WB&G!+KnWfR>l3bdN#y5qWa8~;7$b(!=ZA2j6l4-DmaYd zvI(N09lz;AZ4=)YA-`7FJ&pNBwOMH}f+vM9vGVEfc9|!D1s)@>`(y-aKi9~}132(Z zqG%7RM`>QSi|3+U@PdyCXO6dLYR=jJ4(C`FWsC?E>)YV z2~78#X#$Iopa~G{hw6p;YU+^zG4{e=&qn2RDcqLxlGZ`XzI3kTXRMq$Hv9H-lqO+e z&+|o(qoC#6oVz38Hq`k#^1dATw%>Zj>y1D+M7L9EXTihBLem{x2=&!rIqc^UHHtzd z>ry{wfGL0MdcKtzWN(kHd~U2e_|b)cF~9-Y!7xB%=Y{**nLf{VoTTd(MrBMJEg6R` z`&-(|lF#ONnGSr*?XX_lf^+A^vLgk*o1liu(eG=qZnZR~XwOa?!*1NRd+~MiDo95N zUZ^hK`&W_g4X>-_{|_JBrd4UHStZR&=TXASYdtQ;R{n>x@M1?hh%*VVsIhJ!2`eQX{%_ZHeV>Mr|lQQnL?su`^&jQ&rSNm+-Qq8O+dAxF zTOX=xJ1`l&ZdY9H?&`q-%aMPAa@zVwVr;-Qk?}?r&wj}pj$5+k$MyOp@fN#*Fpt)~ z;rVc&ARHmCcwH3keW#2QNg2vD zq9Y~hw40Lw@GIb&vE6OHS^PW;zy3tvSDlx2gJR&2MRwZ8?c*BU@^upXp1T9Q-s;D# zuzyYu57?jX=H~0}7kFO<08$@t!Fu&CkdB&{t`p$y9vmJ{${){V9yU{`yzYR0sIRen z{V%5jBA`$NdFBqLwE-ia)W^&6oOgPf>(`%2EByD#{Eu$iPyJxiWlh!}n2VHBiL1DF zw8E57P9cR<;>QF&xVSEk+-sNwt&0EroyXV~p%lV%11;yt%5CRR4eGb4xHW_rDu%S% zVRTRT#h%jBoeCMR}1%gM#t`f-Uf zmgZyR;r+<+FqnV;t}&=Bd%11bmdUO}%7}5<7V&^5tQk_uI~v60f)e}16KQbUVA@Y! zng2h2^?^sain@Hd7(`|Le^MSBH-L{3GuJs#yeF1d|;EQ2AS zn5;auJl1av;scTjX*FG{{X3_B>tE`3eCzRjrXL=jo&tAHe3_pfWvt$}pHc~$JU?vM z@{-tvGjw<=N%BmN|NP!p`qh?J2+yOC{^y{LeH0|NTliU$(HL zHrfB?f~35dwUz$={!4^2=gy=ePYHVh@G0vB^qyfo-pQb#&;rEu{0I-;cI$~d8DZ&jauwFare2-al@(6w`m)D6HE!E#jU9B~9RTHPT#cjNQCIUCcgR zy%Pn2RAr{r^BTk94C7w>h654GGuNnDg2!}Cbhx9Ros1BhL7QlJcGv`P^4bM;a?RLA{(O=WIU{@>#v5mGPg+_yLY& z9d17G5yO|fBAE`kCBA`fvC9K~8N(OlN+DkT$alblX+<2t0q)`B|9A!;!lQ$IhjK&~ zA3>%?KwLqfjk|z*2YWtQ0hOnTxyu)^5SzuJrWP%H8ff-=Ci#1R${?vRi0jm7S-rB@!|_zRYO zAoYj=SR(X=5zlz!)PY}UJ$y&($$6BQa%4CH?-S$)nSgK^b0<~2kQ)*YNV^9n-RL-j z3CoT*u|o#r7;^NnJn}m{2#(<6IaYB&<+F+^H#grhKKzfA>DynY5te{C;jd6v^f-=c zY2!@~nO6>j9N-vb)gS|Z;2aSh8T-0oyc^RnlXNAy^#l~u@{+U?aF2)N4Ckhd@>(hk~{3^Fi<64@#+dczK=E~QYxOw9*!zu z;+fk+V1{r(hbaELY~tjIVlrx`*EU7IMI{>z1#%1}BItK;N6_tKT~;-8-}F5l9O?4Jy|@%GIb%saj#ErkPqt+C2$IupE01S16h??4^%Zh31|xywrn*>UA(whV!( zzUxg}I=4pK|WpR$qr-=D)kMIu6GPvF0 z$yp_t7Z+XKr`X6o?6y!`Wh;Dd7Xm{{6nB;!dfCz!H504Jve5filg z4?FfqPuLO1as@39BZxNw;wYdUCC-Mok8N|>(W}|kfmV*_Kha#KlRS*z&(k;8z;(0? zyyB|T=B&Xx&;a7}GsE<5i6uUQEzESMLE#rc1Njxg#~%~Vay7(8_i4RH+{UPKUoJ=> zIYynm=dw+kpWp}M2R9aR0I?-!R+eLGYed=ENFa&p`LY7r^J_`T!GBh2M>qPbqki@9 zY=otH05;g`RTdCA-Qr?gfstO()%o{Ql9nJk`WE^mk(7LUWA{E7bG(McE^9E7GsaVh z`>Uf8#>#;os*r3?y$+-ofV$yQNCdid!i!(QxhN~eDL-$5U6DlhdXHX5bb}#2cZTdQ z{IYaa(_b;c(Ekv`fc%~A+6TL@_+|UOuhH2r8LH-7)blD~`{tQK^@;gFV98BzHt{;` zTz#Y+(}>IOxg`p|KZqnx$Ue#E5F7cY<^PoJ>2-r^ZvmE&`&J>CR3OP;RC+x0u3fe% zmQ{a?D{#l+7d${JQn}M-9dQJx=DvnHEd(D~=(QhLU%YE|T>_moUtg-oBAxLm9qf=e zC{4YqSnDTPaY8Jn?cL#LP)0QSvoc)`C4lVf@%1!cQeN4wi~zF=9MiN|u*#*lw5tJi zwsDhm-=b@go9xEz&=ehh<1!}}$g+2t?nJHhS%w!TS~k8-ju{8DJxO!GA`JwlVahjZ zA4R-G31pWqdSCsI9lwpIjlU=JxK*u~ov3rDCzYnpH2TwY#a(0IQk$8HhO*o<^BMw` zXw&X*A7vQ=Tku?&L3Qx^@^+&C_2Ywa=kc}SW!H(pI7USqf>{PCvJ$Qz4iRtTtOsI383u9z}=i6XcFgVxz0trQXZit7(Nt=k@&t+fXG&s3MKk=EVeNa zA25NWHt3+u2c;n9;fkKjRC6}3*PQ^yDuA{2bl2PGbAzKV7%O7qm2N4Rph-B#JhlEJ zg&b&;Q-&{~yMNV4vtqL-A*Zl)eIB30MXZeAa#ExqkB*2~7f6zrXyENRgU?#_Jv%Nu zXu5}%)aiKwJ4bWwA!zXGS!=9z6GLeAd+aA1#BQ#LL6be^$9gktHJW|kr0|^aqBGv{ zKi%aibbfLOmTyvL@G?>bA|uwr1^9OMXC~gvuLO?H4C**^uu0~t`=n|%6Bi)v})`T{^6kQ z_E0=;X|?-7g65gi=so8*W#Op(_aeaZMcC(Mh67auEDl>yGZ99Cpjf;YNj?hF6oGL%RUIH{3Mz=blU6<9L z6Pktb)0zx*h7DlXHXgRxYbSXLHOz|F!Sc-N6ehceKa@FCKg$w^F@eH!Ejv5oM7ewb z2%`0W)eXasMZFFfTJU(h-^I+i>O!1)^>cJ-IFg8!i4bE4YY+1giv#sDsTv!xpxZ7X zXjaD-6zg}fP91O!TRJQFwxRW`;LGsgeXlARo#l(jiJQC#uB!oz)J<>&2xaY*aOmC* zGlqoatBe&F>YQ_h>gH*L%RiDx$vM~%O7V-_%@FW-EV&Ov8PG6DR%I?m32hw$IM=cw z5dCgrXVw{pT~k}DnsQF^2@Ymu2NdYe-gY`#kznbjiG||AEpK%1$3E*%e8~3eFZ?>m zn{4soz4oq;d?^85uTArGklYgB7!J_~23eePnVQf&kECo(7+d{Rdlz{7aCo`rJ~<_c}xA=$XD2ffJy&?5Cu6-m#- zPQm11sB&7m(eiluOsdp3sJ`|b>BRZp_2#gHhV!jek|IAM&WDgFX&1OME{0+A>X_rS z^Rq*FbYns(Q|^~lvuvl`UlQv+F}-+pKsa$yOcCNl+7wtpbsS`;Dg8P3Gy}^oX?_z5 zDZ$&>9Jft1gOb$rsJ(orF|8yb>8>Y=?hGO{#MD^=)AFr|)n>NP-*Rr%omG$bwJ||j zCtaQ?6B4zpMgSqw)id;KF)~@mG2=CW*622R#;+tgjpV5pj)zNx$Eu4as%WKT9Nm#^5k80kDNf+qebgiGZQ9g!M6k;CD zRh)e{MQ?jpJ>q<|^2a>bhAC5ys^%(bT)(kTB}NP4 zb)tZ&!aFHy9qj}`RXGr$AZIUs`vq^^{z9YW{ZR?5ksW&eZ6(9x5rIG`%7Pv%J5*5;x-Rnn9^bzj}JuXM8U()53B=8BG8Vp@GGo|5Cgn%>cyr&a3uzE4%G#t zFmb<3@m=b4<53V->3Bnjh1l^%Ib}^@{Eu2?2$z%O`xq|F(BBDu)jHbDAD#_^5*0X& z0FzMMtkRRQmX6-gH{9G+_U`8932H3BX+#`Ch{R~^?X1NzM%VeR?=tm5v&Be85;Ww;Cmnj}b0X_a9`Kc^Gq|976P^$YG{X!+5l#BRQzaI{ZA*V+1 z-0fp*x3G3Tfe+NJy@{~~ohU+2i%Cr1%hQ{Esgc$rqqN!vV#4;V=LO_jWs=u6VrM;j z%ibh_)M$teUT-q3!if{PLu>XpWJnpQ`s~JETl_l3rD*cK(40uYcJT%`&M62(a0Ij^ zQ&Vr6mR9~_MEJ^ImILOv(S~HC2e@!ucgY8H0-(TjWK(M8XOMPod%*@V1(bb z2T&o(LoJoZnznyV0jh+x2=aQGk_$~f-c(g~K23#%79Q(u2M6U%Wx@*+^SAoRhbfhuMn`Mu@FcEZin(UK`ugzTZ+MzM4HTjg67OP54|&ncJ^j=n0Iv)k zUR}Q4Qo+Ou7C#{lH*$(I?faMpxonn}mWH}{c;rw}P>6^K2zWMJJF#k(E#U4sw2ioB zt_nnE&o$Z2e^bd4sRW0y$B%){cmg(X>kOO!Irkf_;#aj#bOAyyNV+9olNbVv+q&lI z2X73T?H7YT@O}il>=< z$?aNAppVT;HGcf@vWGEJq}d@eqK^hOZt#r=clW{lr@`knl$s8MN8&?_nFl{X2-S=!aRroueEXLoaT#H$Iw}*;ToatQt=e?Kc!_|&6 zfjEn|meq=#s~;r&@Si^p5B~w51+=%_Jei@k>ot_lP80>E?d&{M zm!E=yjUKge3u4X!TGk za&W(kw?#HeY@TKh8mNW;Ubd(ZKci9dLDf~&nG^{gXn>##P9A0nQv`Y*?cYA+_R5n~ zJPS=74tMsI7o*p{%dS7$AMvN13JMDf5C5Out~;uUY!A~rqN3CYi1Zd(kRWBL(nN_; zLz7S!LK8%hNGPI9v5*K+iWGye5Kx*FAz8#A0#Y7?PACEb3xo~=@eT0y-}m00cg~wL zbLO9W?%bKV^DE!?&F@kHCsvagTsL#EiXwt`!_ zq2C7C@_`hVZD9H#RVg9e8?XSqc5Z1)Mi?FZnVRfUz-g+cJ$gk+3e;*S+P7NYYJUCX zC}(sDV$5m)1rHDPL&kxF4nzU)lImd!Gy93rf#Kn(5I?`~wA~!Ie8&49O)>4=-QCm^ z1jkUC`k!A%q2Iu>BFkH@mZ&YH>*sv!eEant=T&2a4dc;UU3y-XPJlq*qc~kvd~dLo zrdw`H_J%I_Q@8I^w?ntv-5;;)2_b5iYDQGaPrK%5y>^D_T)E+_huM5{^?5XZ#(L*P zloW=umG}c|XU(`XxBlGW;*fq(3uw7~qAXa(hEplL~Oo zgha~AhUNNX;3!$$DUUf=1U`I%eZe)ktR5u%)n{8J0mi|4Z|?1}NO2(C+Svmn3^A=@Nm^wn^2XG8cyYzvt2P3{j(CfI34{bAH-WM@1Qm1P#a>UsQN~wotX^_1N zyv{zIlQ(6_q?G&HFq9W>qF$9VP*(Wj(6HjcB2JEwy`@On;S&K}x}EY+Eb4noFEGC* z?urGY7UBK@0R?#cgLrnn(~0MIqjM+}duKS@cA-P(n4WPlX2OMiAt_))`qt02o;9^K zleeo<3fMOiE3Z~j1pYr?v=YhiP5GnSv3a^LO?)8Z^?Lbxz9=Z*s~`#BB%YHuc^uPc zk-_&A53jaEV%I0l>2KG0%Ld62?(W4Ll#kx|$P3bo!dl{ceq*ntB<1z)T|bkj;^Qg>Tn!@_S<5Ms;7P?41j ziX05OY;A2VRheg(*4sa@T#ZbQ*6$jw4%qGbIYab-Z{^QS0pT8|b4vTf^z?M<5Yh1D z$yPNy?6ctNXM;wG22T7=0ayw*cRd7EdQMqcmlkh;Q&@fB1~NNUiNW|uAe_80Lh$-VDuzS=bHe*&vVuX&}Bi`(I6bdZQDZ#7NLmXhVV%QDAF!CwIWO9~Y8j%*2PShAC2?dU@5ng~ZI6tadFlI`H%rCKWigS;3L=2S>pG<2f zf9W>=mr+14)duxniw@k`5cBR(9&mQZQA-@e=`Gsx`jc3H2ea-5q=ONF#3eTSQlz>z zP*=W)AskggjX7^Lv@g~v`U_B)1*lt}EQ8kcioR*5e{7L`7+DY3% zd|98R+%5^!UaXTe2NkGO2b9YnA7nvM0ntT{b-=M9ei7H{82<}DrLDOu)TQ?CI9^+_gYx#|$8zs|g z0mq4{N|z$a2{P!AG`-_rwibJEWu97Tj2dHXOL#JYUpo)jXI+~!ll4K)Q=iD8S!BYr zHt%jpMyx;me%;6{fu8l?wE9;5KpD{i)#%Z+{wSV-=rWu4P@EpQ3pvc=5(EYJcAH3F zV#l9N_WY*BDq6O1!4BlyGoWDxYnQsii6YM`y8rwk%f`m$_AYY8EzzEk|EA%Rd@Gah zBe8DtgLE16<|{~Y#4W*)TY2*{Fp^x7khmzqCoHXLIfy>-g#Nuze6K}TY*L5NaCAch z1O_Ia&4`tAV%aowUI|jk<0UEy2O@@u_N(K$}Z}a;C}Krhe0&3Z+ra)m!J-yVhyC zPf`}A>Q#1K9&goX)sKwq1`}!AFzf+9XGaeangQPDdrc9}7 zatNEP+mXvxR=C`aUJ?9Hk58<-|LDzQC+>Dq$LkQSl;yHAw~?AkH?74F>r27ZS$0Oi zqUO$PaWFN9e{fsxMRuBIEz0L1odzGrBSvb=lBc!3G=yCSKGh)UfBvLX$DW5lY4H*` zTvk@p?XH{)O)GpD>*iG_xsMl)Rls1T1<%&yC4kb+G7uNe9!!FXmQ}HcAgv2tep-9K>iO~`i^)|E<-p|JW0fZwVSUB(-BuwMbXJ@bIh3=8VaO*@lm&z!Mp>t z_B@_;tU)ST1>pY?F|nX{m%+r=Yf4+oP>5`JvIWrN^*by7ZeJ3LhjA+Q|0={{2x<+* zCKd6WiM5!}43Qi&i*?HNOyQh4)<(KH9+JoLsIhyO&18LeMqgtq%3BPD5k{<6`8IAp zVYF8e16PN)J(UW89Lq7kDld%4VNOg{<5B+Xj+V0A42_f)coQp}=1u!ky4M#nMrnwj?2rnn`&RD6RNx(y zDg8DrsDI<$3zj3ybD*9f(eRPlyiNr<7l582fgVDB*DW_O)@FW zy^4I|ul$^Zeh_-cs^LyX=6-0+w_tf+3~APc7C1lA+j{8D0BVIhcLfnB$}el0 z5CN<~n)7U9|N@k(Z%k^;y_LCB$68~q^}PL>YT zHr4&=l%r&X716$3ch-o77HITY-MzA7;3$&&VD7S|0|?2Z9DMX#>q}jd0r~_$lig^D zm4=^mZsp-371+3nGp%eEf)$F6{$rE>`vw0J tPW*NL--iD;difho|BEptw153+z|aQuI}`Lk^(+IhS(w_Glo@%%{S)Uy$mIY4 diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css index f6ede66bd9b..a7ef13eadee 100644 --- a/ui/modules/vpc/vpc.css +++ b/ui/modules/vpc/vpc.css @@ -248,17 +248,42 @@ } .vpc-network-chart .tier-item.router .header { - background: #908F8F; padding: 15px 0 14px; border-bottom: 1px solid #808080; + background: #C3C6C9; +/*Old browsers*/ + background: -moz-linear-gradient(top, #c3c6c9 0%, #909497 100%); +/*FF3.6+*/ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c3c6c9), color-stop(100%,#909497)); +/*Chrome,Safari4+*/ + background: -webkit-linear-gradient(top, #c3c6c9 0%,#909497 100%); +/*Chrome10+,Safari5.1+*/ + background: -o-linear-gradient(top, #c3c6c9 0%,#909497 100%); +/*Opera 11.10+*/ + background: -ms-linear-gradient(top, #c3c6c9 0%,#909497 100%); +/*IE10+*/ + background: linear-gradient(to bottom, #c3c6c9 0%,#909497 100%); +/*W3C*/ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c3c6c9', endColorstr='#909497',GradientType=0 ); +/*IE6-8*/ } .vpc-network-chart .tier-item.router .header .title { width: 212px; + margin-top: 3px; } .vpc-network-chart .tier-item.router .header .title span { - padding: 0 0 0 32px; + padding: 0 0 0 50px; +} + +.vpc-network-chart .tier-item.router .header span.icon { + background: url(../../images/sprites.png) -589px -1175px; + padding: 10px 10px 10px 20px; + float: left; + position: absolute; + top: 7px; + left: 10px; } .vpc-network-chart .tier-item.router .dashboard-item { @@ -278,3 +303,7 @@ text-shadow: 0px 1px #000000; } +.vpc-network-chart .tier-item.router .dashboard-item:hover { + background-color: #818181; +} + diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 0f0d3f909d7..2b01648e037 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -35,6 +35,7 @@ }).addClass('router'); $router.find('.info, .detail-link').remove(); + $router.find('.header').prepend($('').addClass('icon').html(' ')); return $router; }, From 3f22b6a3e584002f19f5fa1877c57158b65b598c Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 10 May 2013 15:15:45 -0700 Subject: [PATCH 009/201] Create panel on click of dashboard item --- ui/modules/vpc/vpc.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 2b01648e037..a3922b3ba4f 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -55,11 +55,29 @@ var $dashboardItem = $('

    ').addClass('dashboard-item'); var $name = $('
    ').addClass('name').append($('')); var $total = $('
    ').addClass('total').append($('')); + var id = dashboardItem.id; $name.find('span').html(dashboardItem.name); $total.find('span').html(dashboardItem.total); $dashboardItem.append($total, $name); $dashboardItem.appendTo($dashboard); + + $dashboardItem.click(function() { + $('#browser .container').cloudBrowser('addPanel', { + title: dashboardItem.name, + maximizeIfSelected: true, + complete: function($panel) { + var section = cloudStack.vpc.sections[id]; + var $section = $('
    '); + + if (section.listView) { + $section.listView(section); + } + + $section.appendTo($panel); + } + }); + }); }); return $dashboard; @@ -92,18 +110,22 @@ tier: tier, dashboardItems: [ { + id: 'tierLoadBalancers', name: 'Load balancers', total: 5 }, { + id: 'tierPortForwarders', name: 'Port forwarders', total: 4 }, { + id: 'tierStaticNATs', name: 'Static NATs', total: 3 }, { + id: 'tierVMs', name: 'Virtual Machines', total: 300 } @@ -123,18 +145,22 @@ $router = elems.router({ dashboardItems: [ { + id: 'privateGateways', name: 'Private gateways', total: 1 }, { + id: 'publicIPs', name: 'Public IP addresses', total: 2 }, { + id: 'siteToSiteVPNs', name: 'Site-to-site VPNs', total: 3 }, { + id: 'networkACLLists', name: 'Network ACL lists', total: 2 } From 55ac9c1b0f5fa4299f1b0613c25ce9f6d8415e31 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 10 May 2013 15:25:46 -0700 Subject: [PATCH 010/201] Add private gateway section to new chart --- ui/modules/vpc/vpc.js | 13 ++++++++++++- ui/scripts/vpc.js | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index a3922b3ba4f..ac596266d05 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -8,6 +8,7 @@ var $title = $('
    ').addClass('title').append($('')); var $content = $('
    ').addClass('content'); var $dashboard = elems.dashboard({ + context: args.context, dashboardItems: dashboardItems }); var $detailLink = $('
    ').addClass('detail-link'); @@ -28,6 +29,7 @@ router: function(args) { var $router = elems.tier({ + context: args.context, tier: { name: 'Router', }, @@ -50,6 +52,7 @@ dashboard: function(args) { var $dashboard = $('
    ').addClass('dashboard'); + var context = args.context; $(args.dashboardItems).map(function(index, dashboardItem) { var $dashboardItem = $('
    ').addClass('dashboard-item'); @@ -70,8 +73,14 @@ var section = cloudStack.vpc.sections[id]; var $section = $('
    '); + if ($.isFunction(section)) { + section = cloudStack.vpc.sections[id]() + } + if (section.listView) { - $section.listView(section); + $section.listView($.extend(true, {}, section, { + context: context + })); } $section.appendTo($panel); @@ -107,6 +116,7 @@ $(tiers).map(function(index, tier) { var $tier = elems.tier({ + context: context, tier: tier, dashboardItems: [ { @@ -143,6 +153,7 @@ // Router $router = elems.router({ + context: context, dashboardItems: [ { id: 'privateGateways', diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index dc26265c232..6033f50f6f1 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -277,6 +277,14 @@ }; cloudStack.vpc = { + // nTier sections + sections: { + // Private gateways + privateGateways: function() { + return cloudStack.vpc.gateways.listView() + } + }, + routerDetailView: function() { return { title: 'VPC router details', From daf392685ae5cb4afb5ade906e7eed0a088d2817 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 10 May 2013 15:41:44 -0700 Subject: [PATCH 011/201] Add tier detail view --- ui/modules/vpc/vpc.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index ac596266d05..cb712bc0254 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -2,13 +2,15 @@ var elems = { tier: function(args) { var tier = args.tier; + var context = args.context; var dashboardItems = args.dashboardItems; var $tier = $('
    ').addClass('tier-item'); var $header = $('
    ').addClass('header'); var $title = $('
    ').addClass('title').append($('')); var $content = $('
    ').addClass('content'); + var $browser = $('#browser .container'); var $dashboard = elems.dashboard({ - context: args.context, + context: context, dashboardItems: dashboardItems }); var $detailLink = $('
    ').addClass('detail-link'); @@ -16,6 +18,24 @@ var $cidrLabel = $('').addClass('cidr-label'); var $cidr = $('').addClass('cidr'); + $detailLink.click(function() { + $browser.cloudBrowser('addPanel', { + title: tier.displayname ? tier.displayname : tier.name, + complete: function($panel) { + var $detailView = $('
    ').detailView( + $.extend(true, {}, cloudStack.vpc.tiers.detailView, { + $browser: $browser, + context: $.extend(true, {}, context, { + networks: [tier] + }) + }) + ); + + $detailView.appendTo($panel); + } + }); + }); + $cidrLabel.html('CIDR: '); $cidr.html(tier.cidr); $title.find('span').html(tier.displayname ? tier.displayname : tier.name); @@ -104,7 +124,9 @@ var vpcItem = context.vpc[0]; var $chart = $('
    ').addClass('vpc-network-chart'); var $tiers = $('
    ').addClass('tiers'); + var $toolbar = $('
    ').addClass('toolbar'); + $toolbar.appendTo($chart); $tiers.appendTo($chart); // Get tiers From 2eb29a5d81d8948ccfabb987cb859a2c995091e3 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 10 May 2013 15:42:18 -0700 Subject: [PATCH 012/201] Tier details: disable view all link, ACL tab --- ui/scripts/vpc.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 6033f50f6f1..5109724e5e1 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -1483,6 +1483,9 @@ path: 'network.ipAddresses', label: 'label.menu.ipaddresses', preFilter: function(args) { + return false; + + /// Disabled if (args.context.networks[0].state == 'Destroyed') return false; @@ -1753,7 +1756,7 @@ } }); - var hiddenTabs = ['ipAddresses']; // Disable IP address tab; it is redundant with 'view all' button + var hiddenTabs = ['ipAddresses', 'acl']; // Disable IP address tab; it is redundant with 'view all' button if(networkOfferingHavingELB == false) hiddenTabs.push("addloadBalancer"); From 6ac4f79397193fb7130ab423e1d74a695f5fdc0f Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 10 May 2013 15:48:32 -0700 Subject: [PATCH 013/201] VPC chart: add link to public IP addresses list --- ui/scripts/vpc.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 5109724e5e1..7e1a8c3efc8 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -282,7 +282,10 @@ // Private gateways privateGateways: function() { return cloudStack.vpc.gateways.listView() - } + }, + publicIPs: function() { + return cloudStack.vpc.ipAddresses.listView() + } }, routerDetailView: function() { From df0919bef589bf44d23f9d9e056fe0da9a579034 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 10 May 2013 16:03:44 -0700 Subject: [PATCH 014/201] Add placeholder network ACL list view --- ui/scripts/vpc.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 7e1a8c3efc8..a009db4d45f 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -283,9 +283,24 @@ privateGateways: function() { return cloudStack.vpc.gateways.listView() }, + + // Public IP Addresses publicIPs: function() { return cloudStack.vpc.ipAddresses.listView() - } + }, + + // Network ACL lists + networkACLLists: { + listView: { + fields: { + name: { label: 'label.name' }, + total: { label: 'label.total' } + }, + dataProvider: function(args) { + args.response.success({ data: [] }); + } + } + } }, routerDetailView: function() { From 57d21051bd8828b8581d2ecf8937b9b84dc94de6 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 13 May 2013 11:16:15 -0700 Subject: [PATCH 015/201] Fix typo --- ui/modules/modules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/modules/modules.js b/ui/modules/modules.js index 32c135e3504..1e4cd45c833 100644 --- a/ui/modules/modules.js +++ b/ui/modules/modules.js @@ -16,7 +16,7 @@ // under the License. (function($, cloudStack) { cloudStack.modules = [ - 'vpc' + 'vpc', 'infrastructure', 'vnmcNetworkProvider', 'vnmcAsa1000v' From 40dc2211db4062d614ad8690c988ea451628c019 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 13 May 2013 14:03:58 -0700 Subject: [PATCH 016/201] Implement 'add tier' action handling --- ui/modules/vpc/vpc.js | 65 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index cb712bc0254..22a82509fbf 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -62,10 +62,69 @@ return $router; }, - tierPlaceholder: function() { + tierPlaceholder: function(args) { + var context = args.context; var $placeholder = $('
    ').addClass('tier-placeholder'); $placeholder.append($('').append('Create network')); + $placeholder.click(function() { + var addAction = cloudStack.vpc.tiers.actions.add; + var form = cloudStack.dialog.createForm({ + context: context, + form: addAction.createForm, + after: function(args) { + var $loading = $('
    ').addClass('loading-overlay') + .prependTo($placeholder); + + addAction.action({ + context: context, + data: args.data, + response: { + success: function(args) { + var tier = args.data; + + cloudStack.ui.notifications.add( + // Notification + { + desc: addAction.label + }, + + // Success + function(args) { + $loading.remove(); + // addNewTier({ + // ipAddresses: ipAddresses, + // $browser: $browser, + // tierDetailView: tierDetailView, + // context: $.extend(true, {}, context, { + // networks: [tier] + // }), + // tier: tier, + // acl: acl, + // $tiers: $tiers, + // actions: actions, + // actionPreFilter: actionPreFilter, + // vmListView: vmListView + // }); + }, + + {}, + + // Error + function(args) { + $loading.remove(); + } + ); + }, + error: function(errorMsg) { + cloudStack.dialog.notice({ message: _s(errorMsg) }); + $loading.remove(); + } + } + }); + } + }); + }); return $placeholder; }, @@ -168,7 +227,9 @@ }); // Add placeholder tier - $tiers.append(elems.tierPlaceholder()); + $tiers.append(elems.tierPlaceholder({ + context: context + })); } } }); From c819980338b852a54f411a385e8b979b4b23d578 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 13 May 2013 14:06:43 -0700 Subject: [PATCH 017/201] Add place holder for internal LB --- ui/scripts/vpc.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 6970d474e5f..ad03a2d4cd9 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -219,7 +219,7 @@ args.response.success({ _custom: { jobId: jobID, - getUpdatedItem: function() { + getUpdateIdtem: function() { $(window).trigger('cloudStack.fullRefresh'); } }, @@ -279,6 +279,19 @@ cloudStack.vpc = { // nTier sections sections: { + // Internal load balancers + tierLoadBalancers: { + listView: { + fields: { + name: { label: 'label.name' }, + total: { label: 'label.total' } + }, + dataProvider: function(args) { + args.response.success({ data: [] }); + } + } + } + // Private gateways privateGateways: function() { return cloudStack.vpc.gateways.listView() From 3c24380f9d52ebac5cc3d06cbeac5941c6c6cfe6 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 13 May 2013 14:54:35 -0700 Subject: [PATCH 018/201] Fix typo --- ui/scripts/vpc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index ad03a2d4cd9..e4315b85e23 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -290,7 +290,7 @@ args.response.success({ data: [] }); } } - } + }, // Private gateways privateGateways: function() { From d6ceef2a29a0d32bec1965031eba23bfc4337759 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 13 May 2013 17:05:03 -0700 Subject: [PATCH 019/201] Implement refresh VPC chart --- ui/modules/vpc/vpc.js | 183 +++++++++++++++++++++++++----------------- 1 file changed, 109 insertions(+), 74 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 22a82509fbf..283ae68e13f 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -27,7 +27,10 @@ $browser: $browser, context: $.extend(true, {}, context, { networks: [tier] - }) + }), + onActionComplete: function() { + $tier.closest('.vpc-network-chart').trigger('reload'); + } }) ); @@ -92,6 +95,8 @@ // Success function(args) { $loading.remove(); + $placeholder.closest('.vpc-network-chart').trigger('reload'); + // addNewTier({ // ipAddresses: ipAddresses, // $browser: $browser, @@ -181,90 +186,120 @@ var vpcChart = function(args) { var context = args.context; var vpcItem = context.vpc[0]; - var $chart = $('
    ').addClass('vpc-network-chart'); - var $tiers = $('
    ').addClass('tiers'); - var $toolbar = $('
    ').addClass('toolbar'); - - $toolbar.appendTo($chart); - $tiers.appendTo($chart); - // Get tiers - vpc.tiers.dataProvider({ - context: context, - response: { - success: function(data) { - var tiers = data.tiers; + var chart = function(args) { + args = args ? args : {}; - $(tiers).map(function(index, tier) { - var $tier = elems.tier({ - context: context, - tier: tier, - dashboardItems: [ - { - id: 'tierLoadBalancers', - name: 'Load balancers', - total: 5 - }, - { - id: 'tierPortForwarders', - name: 'Port forwarders', - total: 4 - }, - { - id: 'tierStaticNATs', - name: 'Static NATs', - total: 3 - }, - { - id: 'tierVMs', - name: 'Virtual Machines', - total: 300 - } - ] + var $chart = $('
    ').addClass('vpc-network-chart'); + var $tiers = $('
    ').addClass('tiers'); + var $toolbar = $('
    ').addClass('toolbar'); + var $refresh = $('
    ').addClass('button refresh'); + + $refresh.appendTo($toolbar); + $toolbar.appendTo($chart); + $tiers.appendTo($chart); + + $refresh.click(function() { + $('.vpc-network-chart').trigger('reload'); + }); + + // Get tiers + var $loading = $('
    ').addClass('loading-overlay').prependTo($chart); + vpc.tiers.dataProvider({ + context: context, + response: { + success: function(data) { + var tiers = data.tiers; + + $(tiers).map(function(index, tier) { + var $tier = elems.tier({ + context: context, + tier: tier, + dashboardItems: [ + { + id: 'tierLoadBalancers', + name: 'Load balancers', + total: 5 + }, + { + id: 'tierPortForwarders', + name: 'Port forwarders', + total: 4 + }, + { + id: 'tierStaticNATs', + name: 'Static NATs', + total: 3 + }, + { + id: 'tierVMs', + name: 'Virtual Machines', + total: 300 + } + ] + }); + + $tier.appendTo($tiers); }); - $tier.appendTo($tiers); - }); + // Add placeholder tier + $tiers.append(elems.tierPlaceholder({ + context: context + })); - // Add placeholder tier - $tiers.append(elems.tierPlaceholder({ - context: context - })); + $loading.remove(); + + if (args.complete) { + args.complete($chart); + } + } } - } - }); + }); + + // Router + $router = elems.router({ + context: context, + dashboardItems: [ + { + id: 'privateGateways', + name: 'Private gateways', + total: 1 + }, + { + id: 'publicIPs', + name: 'Public IP addresses', + total: 2 + }, + { + id: 'siteToSiteVPNs', + name: 'Site-to-site VPNs', + total: 3 + }, + { + id: 'networkACLLists', + name: 'Network ACL lists', + total: 2 + } + ] + }).appendTo($chart); + + $chart.bind('reload', function() { + chart({ + complete: function($newChart) { + $chart.replaceWith($newChart); + } + }); + }); + + return $chart; + }; - // Router - $router = elems.router({ - context: context, - dashboardItems: [ - { - id: 'privateGateways', - name: 'Private gateways', - total: 1 - }, - { - id: 'publicIPs', - name: 'Public IP addresses', - total: 2 - }, - { - id: 'siteToSiteVPNs', - name: 'Site-to-site VPNs', - total: 3 - }, - { - id: 'networkACLLists', - name: 'Network ACL lists', - total: 2 - } - ] - }).appendTo($chart); - $('#browser .container').cloudBrowser('addPanel', { title: vpcItem.displaytext ? vpcItem.displaytext : vpcItem.name, maximizeIfSelected: true, complete: function($panel) { + var $chart = chart(); + $chart.appendTo($panel); } }); From ce7802413af89720bcd89a33c3966ab639a3270d Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 13 May 2013 17:26:23 -0700 Subject: [PATCH 020/201] Remove refresh button --- ui/modules/vpc/vpc.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 283ae68e13f..f084affe087 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -193,16 +193,10 @@ var $chart = $('
    ').addClass('vpc-network-chart'); var $tiers = $('
    ').addClass('tiers'); var $toolbar = $('
    ').addClass('toolbar'); - var $refresh = $('
    ').addClass('button refresh'); - $refresh.appendTo($toolbar); $toolbar.appendTo($chart); $tiers.appendTo($chart); - $refresh.click(function() { - $('.vpc-network-chart').trigger('reload'); - }); - // Get tiers var $loading = $('
    ').addClass('loading-overlay').prependTo($chart); vpc.tiers.dataProvider({ From cb31791adf903e16abba720cf483edc1fb18e82c Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 14 May 2013 16:25:37 -0700 Subject: [PATCH 021/201] WIP ACL draggable multi-edit --- ui/scripts/ui/widgets/multiEdit.js | 1394 +++++++++++++++------------- ui/scripts/vpc.js | 85 +- 2 files changed, 819 insertions(+), 660 deletions(-) diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index a1272fda31c..0f1515f5aec 100755 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -30,6 +30,7 @@ var $tr; var $item = $('
    ').addClass('data-item'); var multiRule = data; + var reorder = options.reorder; $item.append($('').append($(''))); $tr = $('').appendTo($item.find('tbody')); @@ -38,339 +39,398 @@ $tr.data('multi-edit-data', itemData); } - // Setup columns - $.each(fields, function(fieldName, field) { - if (options.ignoreEmptyFields && !data[fieldName]) { - return true; - } + // Add reorder actions + if (reorder) { + var sort = function($tr, action) { + var $listView = $tr.closest('.data-body'); + var viewArgs = $listView.data('view-args'); + var context = $.extend( + true, {}, + options.context + ); + var rowIndex = $tr.closest('.data-body').find('.data-item').size() - ($tr.closest('.data-item').index()); - var $td = $(''); + var itemName = multiRule._itemName ? item[multiRule._itemName] : item.name; + var $itemName = $('').html(_s(itemName)); - // Show list view of selected VMs - $browser.cloudBrowser('addPanel', { - title: _l('label.item.listing'), - data: '', - noSelectPanel: true, - maximizeIfSelected: true, - complete: function($newPanel) { - return $newPanel.listView(listViewArgs); + $tr.append($(''); - var itemName = multiRule._itemName ? item[multiRule._itemName] : item.name; - var $itemName = $('').html(_s(itemName)); - - $tr.append($('').appendTo($('
    ').addClass(fieldName).appendTo($tr); - var $input, val; - var $addButton = $multi.find('form .button.add-vm:not(.custom-action)').clone(); - var newItemRows = []; - var addItemAction = function(data) { - var $loading = $('
    ').addClass('loading-overlay'); - var complete = function(args) { - var $tbody = $item.find('.expandable-listing tbody'); + context[viewArgs.activeSection] = $tr.data('json-obj'); - $loading.remove(); - $(data).each(function() { - var item = this; - var $itemRow = _medit.multiItem.itemRow(item, options.itemActions, multiRule, $tbody); - - $itemRow.appendTo($tbody); - newItemRows.push($itemRow); - - cloudStack.evenOdd($tbody, 'tr:visible', { - even: function($elem) { - $elem.removeClass('odd'); - $elem.addClass('even'); - }, - odd: function($elem) { - $elem.removeClass('even'); - $elem.addClass('odd'); - } - }); - }); - }; - var error = function() { - $(newItemRows).each(function() { - var $itemRow = this; - - $itemRow.remove(); - }); - $loading.remove(); - }; - - $loading.prependTo($item); - options.itemActions.add.action({ - context: options.context, - data: data, - multiRule: multiRule, + action.action({ + context: context, + index: rowIndex, response: { - success: function(args) { - var notificationError = function(args) { - error(); - }; - - cloudStack.ui.notifications.add(args.notification, - complete, {}, - notificationError, {}); - }, - error: error + success: function(args) {}, + error: function(args) { + // Move back to previous position + rowActions.moveTo($tr, rowIndex); + } } }); }; - if (!itemData) itemData = [{}]; + $('
    ').addClass('actions reorder').appendTo($tr).append(function() { + var $td = $(this); - if (!options.noSelect && - $multi.find('th,td').filter(function() { - return $(this).attr('rel') == fieldName; - }).is(':hidden')) { - return true; + $.each(reorder, function(actionName, action) { + var fnLabel = { + moveTop: _l('label.move.to.top'), + moveBottom: _l('label.move.to.bottom'), + moveUp: _l('label.move.up.row'), + moveDown: _l('label.move.down.row'), + moveDrag: _l('label.drag.new.position') + }; + + $('
    ') + .addClass('action reorder') + .addClass(actionName) + .append( + $('').addClass('icon').html(' ') + ) + .attr({ + title: _l(fnLabel[actionName]) + }) + .appendTo($td) + .click(function() { + if (actionName == 'moveDrag') return false; + + rowActions[actionName]($tr); + $tr.closest('.data-body').find('.data-item').each(function() { + sort($(this), action); + }); + + return false; + }); + }); + }); + + // Draggable action + var initDraggable = function($dataItem) { + var originalIndex; + + return $dataItem.sortable({ + handle: '.action.moveDrag', + start: function(event, ui) { + originalIndex = ui.item.index(); + }, + stop: function(event, ui) { + $dataItem.closest('.data-body').find('.data-item').each(function() { + sort($(this), reorder.moveDrag); + }); + } + }); + }; + + if (reorder && reorder.moveDrag) { + initDraggable($tr.closest('.data-item')); } + } - if (!field.isPassword) { - if (field.edit) { - // Edit fields append value of data - if (field.range) { - var start = _s(data[field.range[0]]); - var end = _s(data[field.range[1]]); - $td.append($('').html(start + ' - ' + end)); - } else { - var maxLengths = data['_maxLength']; + // Setup columns + $.each(fields, function(fieldName, field) { + if (!field || (options.ignoreEmptyFields && !data[fieldName])) { + return true; + } - if (maxLengths && - maxLengths[fieldName] && - data[fieldName].length >= maxLengths[fieldName]) { - $td.append($('').html(_s(data[fieldName].toString().substr(0, maxLengths[fieldName] - 3).concat('...')))); - } else { - $td.append($('').html(_s(data[fieldName]))); + var $td = $('
    ').addClass(fieldName).appendTo($tr); + var $input, val; + var $addButton = $multi.find('form .button.add-vm:not(.custom-action)').clone(); + var newItemRows = []; + var addItemAction = function(data) { + var $loading = $('
    ').addClass('loading-overlay'); + var complete = function(args) { + var $tbody = $item.find('.expandable-listing tbody'); + + $loading.remove(); + $(data).each(function() { + var item = this; + var $itemRow = _medit.multiItem.itemRow(item, options.itemActions, multiRule, $tbody); + + $itemRow.appendTo($tbody); + newItemRows.push($itemRow); + + cloudStack.evenOdd($tbody, 'tr:visible', { + even: function($elem) { + $elem.removeClass('odd'); + $elem.addClass('even'); + }, + odd: function($elem) { + $elem.removeClass('even'); + $elem.addClass('odd'); } - $td.attr('title', data[fieldName]); - } - } else if (field.select) { - // Get matching option text - var $matchingSelect = $multi.find('select') - .filter(function() { - return $(this).attr('name') == fieldName; - }); - var $matchingOption = $matchingSelect.find('option') - .filter(function() { - return $(this).val() == data[fieldName]; - }); + }); + }); + }; + var error = function() { + $(newItemRows).each(function() { + var $itemRow = this; - var matchingValue = $matchingOption.size() ? - $matchingOption.html() : data[fieldName]; - - $td.append($('').html(_s(matchingValue))); - } else if (field.addButton && !options.noSelect) { - if (options.multipleAdd) { - $addButton.click(function() { - if ($td.hasClass('disabled')) return false; - - _medit.vmList($multi, - options.listView, - options.context, - options.multipleAdd, _l('label.add.vms'), - addItemAction, - { - multiRule: multiRule - }); + $itemRow.remove(); + }); + $loading.remove(); + }; - return true; - }); - $td.append($addButton); + $loading.prependTo($item); + options.itemActions.add.action({ + context: options.context, + data: data, + multiRule: multiRule, + response: { + success: function(args) { + var notificationError = function(args) { + error(); + }; + + cloudStack.ui.notifications.add(args.notification, + complete, {}, + notificationError, {}); + }, + error: error + } + }); + }; + + if (!itemData) itemData = [{}]; + + if (!options.noSelect && + $multi.find('th,td').filter(function() { + return $(this).attr('rel') == fieldName; + }).is(':hidden')) { + return true; + } + + if (!field.isPassword) { + if (field.edit) { + // Edit fields append value of data + if (field.range) { + var start = _s(data[field.range[0]]); + var end = _s(data[field.range[1]]); + + $td.append($('').html(start + ' - ' + end)); + } else { + var maxLengths = data['_maxLength']; + + if (maxLengths && + maxLengths[fieldName] && + data[fieldName].length >= maxLengths[fieldName]) { + $td.append($('').html(_s(data[fieldName].toString().substr(0, maxLengths[fieldName] - 3).concat('...')))); } else { - // Show VM data - var itemName = data._itemName ? itemData[0][data._itemName] : itemData[0].name; - $td.html(options.multipleAdd ? - itemData.length + ' VMs' : itemName); - $td.click(function() { - var $browser = $(this).closest('.detail-view').data('view-args').$browser; - - if (options.multipleAdd) { - _medit.multiItem.details(itemData, $browser); - } else { - _medit.details(itemData[0], $browser, { - context: options.context, itemName: itemName - }); - } - }); + $td.append($('').html(_s(data[fieldName]))); } - } else if (field.custom) { - var $button = $('
    ').addClass('button add-vm custom-action'); + $td.attr('title', data[fieldName]); + } + } else if (field.select) { + // Get matching option text + var $matchingSelect = $multi.find('select') + .filter(function() { + return $(this).attr('name') == fieldName; + }); + var $matchingOption = $matchingSelect.find('option') + .filter(function() { + return $(this).val() == data[fieldName]; + }); - $td.data('multi-custom-data', data[fieldName]); - $button.html(data && data[fieldName] && data[fieldName]['_buttonLabel'] ? - _l(data[fieldName]['_buttonLabel']) : _l(field.custom.buttonLabel)); - $button.click(function() { + var matchingValue = $matchingOption.size() ? + $matchingOption.html() : data[fieldName]; + + $td.append($('').html(_s(matchingValue))); + } else if (field.addButton && !options.noSelect) { + if (options.multipleAdd) { + $addButton.click(function() { if ($td.hasClass('disabled')) return false; - var $button = $(this); - var context = $.extend(true, {}, - options.context ? - options.context : cloudStack.context, { - multiRules: [data] - }); - - field.custom.action({ - context: context, - data: $td.data('multi-custom-data'), - $item: $td, - response: { - success: function(args) { - if (args.data['_buttonLabel']) { - $button.html(_l(args.data['_buttonLabel'])); - } - $td.data('multi-custom-data', args.data); - } - } - }); + _medit.vmList($multi, + options.listView, + options.context, + options.multipleAdd, _l('label.add.vms'), + addItemAction, + { + multiRule: multiRule + }); return true; }); - $button.appendTo($td); - } - } + $td.append($addButton); + } else { + // Show VM data + var itemName = data._itemName ? itemData[0][data._itemName] : itemData[0].name; + $td.html(options.multipleAdd ? + itemData.length + ' VMs' : itemName); + $td.click(function() { + var $browser = $(this).closest('.detail-view').data('view-args').$browser; - // Add blank styling for empty fields - if ($td.html() == '') { - $td.addClass('blank'); - } - - // Align width to main header - _medit.refreshItemWidths($multi); - - if (data._hideFields && - $.inArray(fieldName, data._hideFields) > -1) { - $td.addClass('disabled'); - } - - return true; - }); - - // Actions column - var $actions = $('
    ').addClass('multi-actions').appendTo($item.find('tr')); - - // Align action column width - $actions.width($multi.find('th.multi-actions').width() + 4); - - // Action filter - var allowedActions = options.preFilter ? options.preFilter({ - actions: $.map(actions, function(value, key) { return key; }), - context: $.extend(true, {}, options.context, { - multiRule: [data], - actions: $.map(actions, function(value, key) { return key; }) - }) - }) : null; - - // Append actions - $.each(actions, function(actionID, action) { - if (allowedActions && $.inArray(actionID, allowedActions) == -1) return true; - - $actions.append( - $('
    ').addClass('action') - .addClass(actionID) - .append($('').addClass('icon')) - .attr({ title: _l(action.label) }) - .click(function() { - var performAction = function(actionOptions) { - if (!actionOptions) actionOptions = {}; - - action.action({ - context: $.extend(true, {}, options.context, { - multiRule: [data] - }), - data: actionOptions.data, - response: { - success: function(args) { - var notification = args ? args.notification : null; - var _custom = args ? args._custom : null; - if (notification) { - $('.notifications').notifications('add', { - section: 'network', - desc: notification.label, - interval: 3000, - _custom: _custom, - poll: function(args) { - var complete = args.complete; - var error = args.error; - - notification.poll({ - _custom: args._custom, - complete: function(args) { - if (isDestroy) { - $loading.remove(); - $dataItem.remove(); - } else { - $multi.trigger('refresh'); - } - - complete(); - - if (actionOptions.complete) actionOptions.complete(); - }, - error: function(args) { - error(args); - $loading.remove(); - $dataItem.show(); - - return cloudStack.dialog.error; - } - }); - } - }); - } else { - $loading.remove(); - if (isDestroy) { - $dataItem.remove(); - } - } - }, - error: function(message) { - cloudStack.dialog.notice({ message: message }); - $item.show(); - $loading.remove(); - } - } + if (options.multipleAdd) { + _medit.multiItem.details(itemData, $browser); + } else { + _medit.details(itemData[0], $browser, { + context: options.context, itemName: itemName }); - }; + } + }); + } + } else if (field.custom) { + var $button = $('
    ').addClass('button add-vm custom-action'); - var $target = $(this); - var $dataItem = $target.closest('.data-item'); - var $expandable = $dataItem.find('.expandable-listing'); - var isDestroy = $target.hasClass('destroy'); - var isEdit = $target.hasClass('edit'); - var createForm = action.createForm; + $td.data('multi-custom-data', data[fieldName]); + $button.html(data && data[fieldName] && data[fieldName]['_buttonLabel'] ? + _l(data[fieldName]['_buttonLabel']) : _l(field.custom.buttonLabel)); + $button.click(function() { + if ($td.hasClass('disabled')) return false; + + var $button = $(this); + var context = $.extend(true, {}, + options.context ? + options.context : cloudStack.context, { + multiRules: [data] + }); - if (isDestroy) { - var $loading = _medit.loadingItem($multi, _l('label.removing') + '...'); - - if ($expandable.is(':visible')) { - $expandable.slideToggle(function() { - $dataItem.hide(); - $dataItem.after($loading); - }); - } else { - // Loading appearance - $dataItem.hide(); - $dataItem.after($loading); + field.custom.action({ + context: context, + data: $td.data('multi-custom-data'), + $item: $td, + response: { + success: function(args) { + if (args.data['_buttonLabel']) { + $button.html(_l(args.data['_buttonLabel'])); + } + $td.data('multi-custom-data', args.data); } } + }); - if (!isEdit) { - if (createForm) { - cloudStack.dialog.createForm({ - form: createForm, - after: function(args) { - var $loading = $('
    ').addClass('loading-overlay').prependTo($dataItem); - performAction({ data: args.data, complete: function() { - $multi.trigger('refresh'); - } }); + return true; + }); + $button.appendTo($td); + } + } + + // Add blank styling for empty fields + if ($td.html() == '') { + $td.addClass('blank'); + } + + // Align width to main header + _medit.refreshItemWidths($multi); + + if (data._hideFields && + $.inArray(fieldName, data._hideFields) > -1) { + $td.addClass('disabled'); + } + + return true; + }); + + // Actions column + var $actions = $('
    ').addClass('multi-actions').appendTo($item.find('tr')); + + // Align action column width + $actions.width($multi.find('th.multi-actions').width() + 4); + + // Action filter + var allowedActions = options.preFilter ? options.preFilter({ + actions: $.map(actions, function(value, key) { return key; }), + context: $.extend(true, {}, options.context, { + multiRule: [data], + actions: $.map(actions, function(value, key) { return key; }) + }) + }) : null; + + // Append actions + $.each(actions, function(actionID, action) { + if (allowedActions && $.inArray(actionID, allowedActions) == -1) return true; + + $actions.append( + $('
    ').addClass('action') + .addClass(actionID) + .append($('').addClass('icon')) + .attr({ title: _l(action.label) }) + .click(function() { + var performAction = function(actionOptions) { + if (!actionOptions) actionOptions = {}; + + action.action({ + context: $.extend(true, {}, options.context, { + multiRule: [data] + }), + data: actionOptions.data, + response: { + success: function(args) { + var notification = args ? args.notification : null; + var _custom = args ? args._custom : null; + if (notification) { + $('.notifications').notifications('add', { + section: 'network', + desc: notification.label, + interval: 3000, + _custom: _custom, + poll: function(args) { + var complete = args.complete; + var error = args.error; + + notification.poll({ + _custom: args._custom, + complete: function(args) { + if (isDestroy) { + $loading.remove(); + $dataItem.remove(); + } else { + $multi.trigger('refresh'); + } + + complete(); + + if (actionOptions.complete) actionOptions.complete(); + }, + error: function(args) { + error(args); + $loading.remove(); + $dataItem.show(); + + return cloudStack.dialog.error; + } + }); + } + }); + } else { + $loading.remove(); + if (isDestroy) { + $dataItem.remove(); + } } - }); - } else { - performAction(); - } - } else { - // Get editable fields - var editableFields = {}; - - $.each(fields, function(key, field) { - if (field.isEditable) editableFields[key] = $.extend(true, {}, field, { - defaultValue: data[key] - }); - }); - - cloudStack.dialog.createForm({ - form: { - title: 'Edit rule', - desc: '', - fields: editableFields }, + error: function(message) { + cloudStack.dialog.notice({ message: message }); + $item.show(); + $loading.remove(); + } + } + }); + }; + + var $target = $(this); + var $dataItem = $target.closest('.data-item'); + var $expandable = $dataItem.find('.expandable-listing'); + var isDestroy = $target.hasClass('destroy'); + var isEdit = $target.hasClass('edit'); + var createForm = action.createForm; + var reorder = options.reorder; + + if (isDestroy) { + var $loading = _medit.loadingItem($multi, _l('label.removing') + '...'); + + if ($expandable.is(':visible')) { + $expandable.slideToggle(function() { + $dataItem.hide(); + $dataItem.after($loading); + }); + } else { + // Loading appearance + $dataItem.hide(); + $dataItem.after($loading); + } + } + + if (!isEdit) { + if (createForm) { + cloudStack.dialog.createForm({ + form: createForm, after: function(args) { var $loading = $('
    ').addClass('loading-overlay').prependTo($dataItem); performAction({ data: args.data, complete: function() { @@ -378,324 +438,336 @@ } }); } }); + } else { + performAction(); } - }) - ); - }); + } else { + // Get editable fields + var editableFields = {}; - // Add tagger action - if (options.tags) { - $actions.prepend( - $('
    ') - .addClass('action editTags') - .attr('title', _l('label.edit.tags')) - .append($('').addClass('icon')) - .click(function() { - $('
    ') - .dialog({ - dialogClass: 'editTags', - title: _l('label.edit.tags'), - width: 400, - buttons: [ - { - text: _l('label.done'), - 'class': 'ok', - click: function() { - $(this).dialog('destroy'); - $('div.overlay:last').remove(); + $.each(fields, function(key, field) { + if (field && field.isEditable) editableFields[key] = $.extend(true, {}, field, { + defaultValue: data[key] + }); + }); - return true; - } + cloudStack.dialog.createForm({ + form: { + title: 'Edit rule', + desc: '', + fields: editableFields + }, + after: function(args) { + var $loading = $('
    ').addClass('loading-overlay').prependTo($dataItem); + performAction({ data: args.data, complete: function() { + $multi.trigger('refresh'); + } }); + } + }); + } + }) + ); + }); + + // Add tagger action + if (options.tags) { + $actions.prepend( + $('
    ') + .addClass('action editTags') + .attr('title', _l('label.edit.tags')) + .append($('').addClass('icon')) + .click(function() { + $('
    ') + .dialog({ + dialogClass: 'editTags', + title: _l('label.edit.tags'), + width: 400, + buttons: [ + { + text: _l('label.done'), + 'class': 'ok', + click: function() { + $(this).dialog('destroy'); + $('div.overlay:last').remove(); + + return true; } - ] - }) - .append( - $('
    ').addClass('multi-edit-tags').tagger($.extend(true, {}, options.tags, { - context: $.extend(true, {}, options.context, { - multiRule: [multiRule] - }) - })) - ) - .closest('.ui-dialog').overlay(); + } + ] + }) + .append( + $('
    ').addClass('multi-edit-tags').tagger($.extend(true, {}, options.tags, { + context: $.extend(true, {}, options.context, { + multiRule: [multiRule] + }) + })) + ) + .closest('.ui-dialog').overlay(); + + return false; + }) + ) + } + + // Add expandable listing, for multiple-item + if (options.multipleAdd) { + // Create expandable box + _medit.multiItem.expandable($item.find('tr').data('multi-edit-data'), + options.itemActions, + multiRule).appendTo($item); + + // Expandable icon/action + $item.find('td:first').prepend( + $('
    ').addClass('expand').click(function() { + $item.closest('.data-item').find('.expandable-listing').slideToggle(); + })); + } + + return $item; + }, + + vmList: function($multi, listView, context, isMultipleAdd, label, complete, options) { + if (!options) options = {}; + + // Create a listing of instances, based on limited information + // from main instances list view + var $listView; + var instances = $.extend(true, {}, listView, { + context: $.extend(true, {}, context, { + multiData: getMultiData($multi), + multiRule: options.multiRule ? [options.multiRule] : null + }), + uiCustom: true + }); + + instances.listView.actions = { + select: { + label: 'Select instance', + type: isMultipleAdd ? 'checkbox' : 'radio', + action: { + uiCustom: function(args) { + var $item = args.$item; + var $input = $item.find('td.actions input:visible'); + + if ($input.attr('type') == 'checkbox') { + if ($input.is(':checked')) + $item.addClass('multi-edit-selected'); + else + $item.removeClass('multi-edit-selected'); + } else { + $item.siblings().removeClass('multi-edit-selected'); + $item.addClass('multi-edit-selected'); + } + } + } + } + }; + + $listView = $('
    ').listView(instances); + + // Change action label + $listView.find('th.actions').html(_l('Select')); + + var $dataList = $listView.addClass('multi-edit-add-list').dialog({ + dialogClass: 'multi-edit-add-list panel', + width: 825, + title: label, + buttons: [ + { + text: _l('label.apply'), + 'class': 'ok', + click: function() { + if (!$listView.find('input[type=radio]:checked, input[type=checkbox]:checked').size()) { + cloudStack.dialog.notice({ message: _l('message.select.item')}); return false; - }) - ) - } - - // Add expandable listing, for multiple-item - if (options.multipleAdd) { - // Create expandable box - _medit.multiItem.expandable($item.find('tr').data('multi-edit-data'), - options.itemActions, - multiRule).appendTo($item); - - // Expandable icon/action - $item.find('td:first').prepend( - $('
    ').addClass('expand').click(function() { - $item.closest('.data-item').find('.expandable-listing').slideToggle(); - })); - } - - return $item; - }, - - vmList: function($multi, listView, context, isMultipleAdd, label, complete, options) { - if (!options) options = {}; - - // Create a listing of instances, based on limited information - // from main instances list view - var $listView; - var instances = $.extend(true, {}, listView, { - context: $.extend(true, {}, context, { - multiData: getMultiData($multi), - multiRule: options.multiRule ? [options.multiRule] : null - }), - uiCustom: true - }); - - instances.listView.actions = { - select: { - label: 'Select instance', - type: isMultipleAdd ? 'checkbox' : 'radio', - action: { - uiCustom: function(args) { - var $item = args.$item; - var $input = $item.find('td.actions input:visible'); - - if ($input.attr('type') == 'checkbox') { - if ($input.is(':checked')) - $item.addClass('multi-edit-selected'); - else - $item.removeClass('multi-edit-selected'); - } else { - $item.siblings().removeClass('multi-edit-selected'); - $item.addClass('multi-edit-selected'); - } } + + $dataList.fadeOut(function() { + complete($.map( + $listView.find('tr.multi-edit-selected'), + + // Attach VM data to row + function(elem) { + var itemData = $(elem).data('json-obj'); + var $subselect = $(elem).find('.subselect select'); + + // Include subselect data + if ($subselect && $subselect.val()) { + return $.extend(itemData, { + _subselect: $subselect.val() + }); + } + + return itemData; + } + )); + $dataList.remove(); + }); + + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); + + return true; + } + }, + { + text: _l('label.cancel'), + 'class': 'cancel', + click: function() { + $dataList.fadeOut(function() { + $dataList.remove(); + }); + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); } } - }; + ] + }).parent('.ui-dialog').overlay(); + }, - $listView = $('
    ').listView(instances); + /** + * Align width of each data row to main header + */ + refreshItemWidths: function($multi) { + $multi.find('.data-body').width( + $multi.find('form > table.multi-edit').width() + ); - // Change action label - $listView.find('th.actions').html(_l('Select')); + $multi.find('.data tr').filter(function() { + return !$(this).closest('.expandable-listing').size(); + }).each(function() { + var $tr = $(this); - var $dataList = $listView.addClass('multi-edit-add-list').dialog({ - dialogClass: 'multi-edit-add-list panel', - width: 825, - title: label, - buttons: [ - { - text: _l('label.apply'), - 'class': 'ok', - click: function() { - if (!$listView.find('input[type=radio]:checked, input[type=checkbox]:checked').size()) { - cloudStack.dialog.notice({ message: _l('message.select.item')}); + $tr.find('td').each(function() { + var $td = $(this); - return false; - } - - $dataList.fadeOut(function() { - complete($.map( - $listView.find('tr.multi-edit-selected'), - - // Attach VM data to row - function(elem) { - var itemData = $(elem).data('json-obj'); - var $subselect = $(elem).find('.subselect select'); - - // Include subselect data - if ($subselect && $subselect.val()) { - return $.extend(itemData, { - _subselect: $subselect.val() - }); - } - - return itemData; - } - )); - $dataList.remove(); - }); - - $('div.overlay').fadeOut(function() { - $('div.overlay').remove(); - }); - - return true; - } - }, - { - text: _l('label.cancel'), - 'class': 'cancel', - click: function() { - $dataList.fadeOut(function() { - $dataList.remove(); - }); - $('div.overlay').fadeOut(function() { - $('div.overlay').remove(); - }); - } - } - ] - }).parent('.ui-dialog').overlay(); - }, - - /** - * Align width of each data row to main header - */ - refreshItemWidths: function($multi) { - $multi.find('.data-body').width( - $multi.find('form > table.multi-edit').width() - ); - - $multi.find('.data tr').filter(function() { - return !$(this).closest('.expandable-listing').size(); - }).each(function() { - var $tr = $(this); - - $tr.find('td').each(function() { - var $td = $(this); - - $td.width($($multi.find('th:visible')[$td.index()]).width() + 5); - }); + $td.width($($multi.find('th:visible')[$td.index()]).width() + 5); }); - }, + }); + }, - /** - * Create a fake 'loading' item box - */ - loadingItem: function($multi, label) { - var $loading = $('
    ').addClass('data-item loading'); + /** + * Create a fake 'loading' item box + */ + loadingItem: function($multi, label) { + var $loading = $('
    ').addClass('data-item loading'); - // Align height with existing items - var $row = $multi.find('.data-item:first'); + // Align height with existing items + var $row = $multi.find('.data-item:first'); - // Set label - if (label) { - $loading.append( - $('
    ').addClass('label').append( - $('').html(_l(label)) - ) - ); + // Set label + if (label) { + $loading.append( + $('
    ').addClass('label').append( + $('').html(_l(label)) + ) + ); + } + + return $loading; + }, + details: function(data, $browser, options) { + if (!options) options = {}; + + var detailViewArgs, $detailView; + + detailViewArgs = $.extend(true, {}, cloudStack.sections.instances.listView.detailView); + detailViewArgs.actions = null; + detailViewArgs.$browser = $browser; + detailViewArgs.id = data.id; + detailViewArgs.jsonObj = data; + detailViewArgs.context = options.context; + + $browser.cloudBrowser('addPanel', { + title: options.itemName ? options.itemName : data.name, + maximizeIfSelected: true, + complete: function($newPanel) { + $newPanel.detailView(detailViewArgs); } + }); + }, + multiItem: { + /** + * Show listing of load balanced VMs + */ + details: function(data, $browser) { + var listViewArgs, $listView; - return $loading; - }, - details: function(data, $browser, options) { - if (!options) options = {}; - - var detailViewArgs, $detailView; - - detailViewArgs = $.extend(true, {}, cloudStack.sections.instances.listView.detailView); - detailViewArgs.actions = null; - detailViewArgs.$browser = $browser; - detailViewArgs.id = data.id; - detailViewArgs.jsonObj = data; - detailViewArgs.context = options.context; + // Setup list view + listViewArgs = $.extend(true, {}, cloudStack.sections.instances); + listViewArgs.listView.actions = null; + listViewArgs.listView.filters = null; + listViewArgs.$browser = $browser; + listViewArgs.listView.detailView.actions = null; + listViewArgs.listView.dataProvider = function(args) { + setTimeout(function() { + args.response.success({ + data: data + }); + }, 50); + }; + $listView = $('
    ').listView(listViewArgs); + // Show list view of selected VMs $browser.cloudBrowser('addPanel', { - title: options.itemName ? options.itemName : data.name, + title: _l('label.item.listing'), + data: '', + noSelectPanel: true, maximizeIfSelected: true, complete: function($newPanel) { - $newPanel.detailView(detailViewArgs); + return $newPanel.listView(listViewArgs); } }); }, - multiItem: { - /** - * Show listing of load balanced VMs - */ - details: function(data, $browser) { - var listViewArgs, $listView; - // Setup list view - listViewArgs = $.extend(true, {}, cloudStack.sections.instances); - listViewArgs.listView.actions = null; - listViewArgs.listView.filters = null; - listViewArgs.$browser = $browser; - listViewArgs.listView.detailView.actions = null; - listViewArgs.listView.dataProvider = function(args) { - setTimeout(function() { - args.response.success({ - data: data - }); - }, 50); - }; - $listView = $('
    ').listView(listViewArgs); + itemRow: function(item, itemActions, multiRule, $tbody) { + var $tr = $('
    ').addClass('name').appendTo($tr).append($itemName)); + + $itemName.click(function() { + _medit.details(item, $('#browser .container'), { + itemName: itemName, + context: { + instances: [item] } }); - }, + }); - itemRow: function(item, itemActions, multiRule, $tbody) { - var $tr = $('
    ').addClass('name').appendTo($tr).append($itemName)); - - $itemName.click(function() { - _medit.details(item, $('#browser .container'), { - itemName: itemName, - context: { - instances: [item] - } - }); - }); - - var itemState=multiRule._itemState ? item[multiRule._itemState] :item.state; - var $itemState = $('').html(_s(itemState)); - $tr.append($('').addClass('state').appendTo($tr).append("Application State - ").append($itemState)); + var itemState=multiRule._itemState ? item[multiRule._itemState] :item.state; + var $itemState = $('').html(_s(itemState)); + $tr.append($('').addClass('state').appendTo($tr).append("Application State - ").append($itemState)); - if (itemActions) { - var $itemActions = $('').addClass('actions item-actions'); + if (itemActions) { + var $itemActions = $('').addClass('actions item-actions'); - $.each(itemActions, function(itemActionID, itemAction) { - if (itemActionID == 'add') - return true; - - if(item._hideActions != null && $.inArray(itemActionID, item._hideActions) > -1) - return true; + $.each(itemActions, function(itemActionID, itemAction) { + if (itemActionID == 'add') + return true; + + if(item._hideActions != null && $.inArray(itemActionID, item._hideActions) > -1) + return true; - var $itemAction = $('
    ').addClass('action').addClass(itemActionID); + var $itemAction = $('
    ').addClass('action').addClass(itemActionID); - $itemAction.click(function() { - itemAction.action({ - item: item, - multiRule: multiRule, - response: { - success: function(args) { - if (itemActionID == 'destroy') { - var notification = args.notification; - var success = function(args) { $tr.remove(); }; - var successArgs = {}; - var error = function(args) { - $tr.show(); - cloudStack.evenOdd($tbody, 'tr:visible', { - even: function($elem) { - $elem.removeClass('odd'); - $elem.addClass('even'); - }, - odd: function($elem) { - $elem.removeClass('even'); - $elem.addClass('odd'); - } - }); - }; - var errorArgs = {}; - - $tr.hide(); + $itemAction.click(function() { + itemAction.action({ + item: item, + multiRule: multiRule, + response: { + success: function(args) { + if (itemActionID == 'destroy') { + var notification = args.notification; + var success = function(args) { $tr.remove(); }; + var successArgs = {}; + var error = function(args) { + $tr.show(); cloudStack.evenOdd($tbody, 'tr:visible', { even: function($elem) { $elem.removeClass('odd'); @@ -706,83 +778,106 @@ $elem.addClass('odd'); } }); - cloudStack.ui.notifications.add(notification, - success, successArgs, - error, errorArgs); - } - }, - error: function(message) { - if (message) { - cloudStack.dialog.notice({ message: message }); - } + }; + var errorArgs = {}; + + $tr.hide(); + cloudStack.evenOdd($tbody, 'tr:visible', { + even: function($elem) { + $elem.removeClass('odd'); + $elem.addClass('even'); + }, + odd: function($elem) { + $elem.removeClass('even'); + $elem.addClass('odd'); + } + }); + cloudStack.ui.notifications.add(notification, + success, successArgs, + error, errorArgs); + } + }, + error: function(message) { + if (message) { + cloudStack.dialog.notice({ message: message }); } } - }); + } }); - $itemAction.append($('').addClass('icon')); - $itemAction.appendTo($itemActions); - - return true; }); + $itemAction.append($('').addClass('icon')); + $itemAction.appendTo($itemActions); - $itemActions.appendTo($tr); - } - - return $tr; - }, - - expandable: function(data, itemActions, multiRule) { - var $expandable = $('
    ').addClass('expandable-listing'); - var $tbody = $('
    ').appendTo($expandable)); - - $(data).each(function() { - var field = this; - var $tr = _medit.multiItem.itemRow(field, itemActions, multiRule, $tbody).appendTo($tbody); - - cloudStack.evenOdd($tbody, 'tr', { - even: function($elem) { - $elem.addClass('even'); - }, - odd: function($elem) { - $elem.addClass('odd'); - } - }); + return true; }); - return $expandable.hide(); + $itemActions.appendTo($tr); } + + return $tr; + }, + + expandable: function(data, itemActions, multiRule) { + var $expandable = $('
    ').addClass('expandable-listing'); + var $tbody = $('
    ').appendTo($('
    ').appendTo($expandable)); + + $(data).each(function() { + var field = this; + var $tr = _medit.multiItem.itemRow(field, itemActions, multiRule, $tbody).appendTo($tbody); + + cloudStack.evenOdd($tbody, 'tr', { + even: function($elem) { + $elem.addClass('even'); + }, + odd: function($elem) { + $elem.addClass('odd'); + } + }); + }); + + return $expandable.hide(); } - }; + } +}; - $.fn.multiEdit = function(args) { - var dataProvider = args.dataProvider; - var multipleAdd = args.multipleAdd; - var tags = args.tags; - var $multi = $('
    ').addClass('multi-edit').appendTo(this); - var $multiForm = $('
    ').appendTo($multi); - var $inputTable = $('
    ').addClass('multi-edit').appendTo($multiForm); - var $dataTable = $('
    ').addClass('data').appendTo($multi); - var $addVM; - var fields = args.fields; - var actions = args.actions; - var itemActions = multipleAdd ? args.itemActions : null; - var noSelect = args.noSelect; - var context = args.context; - var ignoreEmptyFields = args.ignoreEmptyFields; - var actionPreFilter = args.actionPreFilter; - var readOnlyCheck = args.readOnlyCheck; +$.fn.multiEdit = function(args) { + var dataProvider = args.dataProvider; + var multipleAdd = args.multipleAdd; + var tags = args.tags; + var $multi = $('
    ').addClass('multi-edit').appendTo(this); + var $multiForm = $('').appendTo($multi); + var $inputTable = $('
    ').addClass('multi-edit').appendTo($multiForm); + var $dataTable = $('
    ').addClass('data').appendTo($multi); + var $addVM; + var fields = args.fields; + var actions = args.actions; + var itemActions = multipleAdd ? args.itemActions : null; + var noSelect = args.noSelect; + var context = args.context; + var ignoreEmptyFields = args.ignoreEmptyFields; + var actionPreFilter = args.actionPreFilter; + var readOnlyCheck = args.readOnlyCheck; + var reorder = args.reorder; - var $thead = $('
    ').appendTo( - $('').appendTo($inputTable) - ); - var $inputForm = $('').appendTo( - $('').appendTo($inputTable) - ); - var $dataBody = $('
    ').addClass('data-body').appendTo($dataTable); + var $thead = $('
    ').appendTo( + $('').appendTo($inputTable) + ); + var $inputForm = $('').appendTo( + $('').appendTo($inputTable) + ); + var $dataBody = $('
    ').addClass('data-body').appendTo($dataTable); - // Setup input table headers - $.each(args.fields, function(fieldName, field) { - var $th = $('
    ').addClass(fieldName).html(_l(field.label.toString())); + // Setup input table headers + + if (reorder) { + $('').addClass('reorder').appendTo($thead); + $('').addClass('reorder').appendTo($inputForm); + } + + $.each(args.fields, function(fieldName, field) { + if (!field) return true; + + var $th = $('').addClass(fieldName).html(_l(field.label.toString())); $th.attr('rel', fieldName); $th.appendTo($thead); var $td = $('').addClass(fieldName); @@ -1055,7 +1150,8 @@ ignoreEmptyFields: ignoreEmptyFields, preFilter: actionPreFilter, listView: listView, - tags: tags + tags: tags, + reorder: reorder } ).appendTo($dataBody); }); diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 805a089dd5a..3235cd66c20 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -26,7 +26,8 @@ } return hiddenFields; // Returns fields to be hidden - }, + }, + reorder: cloudStack.api.actions.sort('updateAclRule', 'multiRule'), fields: { 'cidrlist': { edit: true, label: 'label.cidr' }, 'protocol': { @@ -45,28 +46,34 @@ var $otherFields = $inputs.filter(function() { var name = $(this).attr('name'); - return name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist'; + return name != 'protocolnumber' && + name != 'icmptype' && + name != 'icmpcode' && + name != 'cidrlist'; }); - var $protocolinput = args.$form.find('th,td'); + var $protocolinput = args.$form.find('td input'); var $protocolFields = $protocolinput.filter(function(){ - var name = $(this).attr('rel'); + var name = $(this).attr('name'); return $.inArray(name,['protocolnumber']) > -1; }); - if($(this).val() == 'protocolnumber' ){ - - $protocolFields.show(); + if($(this).val() == 'protocolnumber' ){ + $icmpFields.hide(); + $otherFields.hide(); + $protocolFields.show(); } else{ - $protocolFields.hide(); + $protocolFields.hide(); + $icmpFields.show(); + $otherFields.show(); } - if ($(this).val() == 'icmp') { $icmpFields.show(); $icmpFields.attr('disabled', false); + $protocolFields.hide(); $otherFields.attr('disabled', 'disabled'); $otherFields.hide(); $otherFields.parent().find('label.error').hide(); @@ -77,6 +84,7 @@ $icmpFields.attr('disabled', 'disabled'); $icmpFields.hide(); $icmpFields.parent().find('label.error').hide(); + $protocolFields.hide(); } }); @@ -93,7 +101,7 @@ } }, - 'protocolnumber': {label:'Protocol Number',isDisabled:true,isHidden:true,edit:true}, + 'protocolnumber': {label:'Protocol Number',edit:true}, 'startport': { edit: true, label: 'label.start.port' }, 'endport': { edit: true, label: 'label.end.port' }, 'networkid': { @@ -305,12 +313,67 @@ // Network ACL lists networkACLLists: { listView: { + id: 'aclLists', fields: { name: { label: 'label.name' }, total: { label: 'label.total' } }, dataProvider: function(args) { - args.response.success({ data: [] }); + args.response.success({ + data: [ + { name: 'ACL list 1', total: 3 }, + { name: 'ACL list 2', total: 2 } + ] + }); + }, + + detailView: { + isMaximized: true, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name', isEditable: true } + } + ], + dataProvider: function(args) { + args.response.success({ data: args.context.aclLists[0] }); + } + }, + + aclRules: { + title: 'label.acl.rules', + custom: function(args) { + return $('
    ').multiEdit($.extend(true, {}, aclMultiEdit, { + context: args.context, + fields: { + networkid: false + }, + dataProvider: function(args) { + args.response.success({ + data: [ + { + cidrlist: '10.1.1.0/24', + protocol: 'TCP', + startport: 22, endport: 22, + networkid: 0, + traffictype: 'Egress' + }, + { + cidrlist: '10.2.1.0/24', + protocol: 'UDP', + startport: 56, endport: 72, + networkid: 0, + trafficType: 'Ingress' + } + ] + }); + } + })); + } + } + } } } } From 08bc6bf77889871f8fd33afab00c139864650f9a Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 11:57:14 -0700 Subject: [PATCH 022/201] Fix 'protocolnumber' change event --- ui/scripts/vpc.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 1d6160a232c..d06ff2ef1ec 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -59,21 +59,14 @@ return $.inArray(name,['protocolnumber']) > -1; }); - if($(this).val() == 'protocolnumber' ){ + if ($(this).val() == 'protocolnumber' ){ $icmpFields.hide(); $otherFields.hide(); - $protocolFields.show(); - } - else{ - $protocolFields.hide(); - $icmpFields.show(); - $otherFields.show(); - } - - if ($(this).val() == 'icmp') { + $protocolFields.show().addClass('required'); + } else if ($(this).val() == 'icmp') { $icmpFields.show(); $icmpFields.attr('disabled', false); - $protocolFields.hide(); + $protocolFields.hide().removeClass('required'); $otherFields.attr('disabled', 'disabled'); $otherFields.hide(); $otherFields.parent().find('label.error').hide(); @@ -84,7 +77,7 @@ $icmpFields.attr('disabled', 'disabled'); $icmpFields.hide(); $icmpFields.parent().find('label.error').hide(); - $protocolFields.hide(); + $protocolFields.hide().removeClass('required'); } }); @@ -98,6 +91,8 @@ ] }); + + setTimeout(function() { args.$select.trigger('change'); }, 100); } }, From 96cee01f705cde7247d2b87f929d14a6d1af3539 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 11:58:40 -0700 Subject: [PATCH 023/201] Add missing license header --- ui/modules/vpc/vpc.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index f084affe087..5c93e6cdbe6 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -1,3 +1,19 @@ +// 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. (function($, cloudStack) { var elems = { tier: function(args) { From 7ed11ee91141cf8315516ea396ed2d3735051135 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 12:09:50 -0700 Subject: [PATCH 024/201] Add site-to-site VPN to VPC chart --- ui/scripts/vpc.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index d06ff2ef1ec..74c78222a10 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -383,6 +383,15 @@ } } } + }, + siteToSiteVPNs: function() { + return $.extend(true, {}, cloudStack.vpc.siteToSiteVPN, { + // siteToSiteVPN is multi-section so doesn't have an explicit + // 'listView' block + // + // -- use this as a flag for VPC chart to render as a list view + listView: true + }); } }, From 42ed9e13f3b14a42207501c80225df028d36eb39 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 12:28:03 -0700 Subject: [PATCH 025/201] Add placeholder tier LB list view + add action --- ui/scripts/vpc.js | 52 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 74c78222a10..96c983b6b02 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -298,11 +298,57 @@ tierLoadBalancers: { listView: { fields: { - name: { label: 'label.name' }, - total: { label: 'label.total' } + ipaddress: { label: 'label.ip.address' }, + type: { label: 'label.type' } }, dataProvider: function(args) { - args.response.success({ data: [] }); + args.response.success({ + data: [ + { ipaddress: '10.3.2.1', type: 'Internal' }, + { ipaddress: '10.3.2.3', type: 'Internal' }, + { ipaddress: '10.232.1.4', type: 'Public' } + ] + }); + }, + actions: { + add: { + label: 'Add new LB', + createForm: { + title: 'Add new LB', + desc: 'Please specify the type of load balancer you would like to create.', + fields: { + type: { + label: 'label.type', + select: function(args) { + args.response.success({ + data: [ + { id: 'internal', description: 'Internal' }, + { id: 'public', description: 'Public' } + ] + }); + } + } + } + }, + messages: { + notification: function(args) { + return 'Add LB to VPC network'; + } + }, + action: function(args) { + args.response.success(); + }, + notification: { + poll: function(args) { + args.complete({ + data: { + ipaddress: '10.0.3.2', + type: 'Internal' + } + }); + } + } + } } } }, From 3bb81313ad0896ca421991d14b5a3497423a6787 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Wed, 15 May 2013 13:59:37 -0700 Subject: [PATCH 026/201] Adnvace Zone with SG enabled: DB upgrade for Advance SG enabled zone - setup name/displayText for Guest Shared SG enabled network (it used to be system network, and name was never set for it in 2.2.x) --- setup/db/db/schema-40to410.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index b7b1c7a91dd..b4c30aebe88 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -1639,3 +1639,7 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Usage', 'DEFAULT', 'manageme INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (163, UUID(), 10, 'Ubuntu 12.04 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (164, UUID(), 10, 'Ubuntu 12.04 (64-bit)'); + +#update shared sg enabled network with not null name in Advance Security Group enabled network +UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain'; + From f985e11c28f451183e64129a774edb4afe460bac Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 15 May 2013 11:01:43 -0700 Subject: [PATCH 027/201] CLOUDSTACK-747: internalLb in VPC - UI - create tier dialog - only one tier is allowed to have PublicLb in a VPC. --- ui/scripts/sharedFunctions.js | 34 +++++++++++----------------------- ui/scripts/vpc.js | 9 +++++---- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index a01840637e3..035299059c2 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -122,34 +122,22 @@ function createURL(apiName, options) { return urlString; } -/* -function fromdb(val) { - return sanitizeXSS(noNull(val)); -} -*/ - function todb(val) { return encodeURIComponent(val); } -/* -function noNull(val) { - if(val == null) - return ""; - else - return val; -} -*/ +//LB provider map +var lbProviderMap = { + "publicLb": { + "non-vpc": ["VirtualRouter", "Netscaler", "F5"], + "vpc": ["VpcVirtualRouter", "Netscaler"] + }, + "internalLb": { + "non-vpc": [], + "vpc": ["InternalLbVm"] + } +}; -/* -function sanitizeXSS(val) { // Prevent cross-site-script(XSS) attack - if(val == null || typeof(val) != "string") - return val; - val = val.replace(//g, ">"); //replace > whose unicode is \u003e - return unescape(val); -} -*/ // Role Functions function isAdmin() { diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 96c983b6b02..c54535dd932 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -2499,15 +2499,16 @@ var items; if(networkSupportingLbExists == true) { items = $.grep(networkOfferings, function(networkOffering) { - var includingLbService = false; + var includingPublicLbService = false; $(networkOffering.service).each(function(){ var thisService = this; - if(thisService.name == "Lb") { - includingLbService = true; + //only one tier is allowed to have PublicLb provider in a VPC + if(thisService.name == "Lb" && lbProviderMap.publicLb.vpc.indexOf(thisService.provider[0].name) != -1) { + includingPublicLbService = true; return false; //break $.each() loop } }); - return !includingLbService; + return !includingPublicLbService; }); } else { From a4fc86ece9fd7c97d308a44b517ccef74053a624 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 14:28:41 -0700 Subject: [PATCH 028/201] Tier LB rules: Add load balancing multi-edit --- ui/scripts/vpc.js | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index c54535dd932..eb3a4b69675 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -297,6 +297,7 @@ // Internal load balancers tierLoadBalancers: { listView: { + id: 'ipAddresses', fields: { ipaddress: { label: 'label.ip.address' }, type: { label: 'label.type' } @@ -349,6 +350,121 @@ } } } + }, + detailView: { + isMaximized: true, + tabs: { + loadBalancing: { + title: 'label.load.balancing', + custom: function(args) { + var context = args.context; + var $multi = $('
    ').addClass('loadBalancer'); + + $multi.multiEdit({ + context: context, + listView: $.extend(true, {}, cloudStack.sections.instances, { + listView: { + fields: { + name: { label: 'label.name' }, + displayname: { label: 'label.display.name' }, + zonename: { label: 'label.zone.name' }, + state: { + label: 'label.state', + indicator: { + 'Running': 'on', + 'Stopped': 'off', + 'Destroyed': 'off', + 'Error': 'off' + } + } + }, + filters: false, + dataProvider: function(args) { + args.response.success({ data: [] }); + } + } + }), + + multipleAdd: true, + + fields: { + 'name': { edit: true, label: 'label.name', isEditable: true }, + 'publicport': { edit: true, label: 'label.public.port' }, + 'privateport': { edit: true, label: 'label.private.port' }, + 'algorithm': { + label: 'label.algorithm', + isEditable: true, + select: function(args) { + args.response.success({ + data: [ + { id: 'roundrobin', name: 'roundrobin', description: _l('label.round.robin') }, + { id: 'leastconn', name: 'leastconn', description: _l('label.least.connections') }, + { id: 'source', name: 'source', description: _l('label.source') } + ] + }); + } + }, + + 'sticky': { + label: 'label.stickiness', + custom: { + buttonLabel: 'label.configure', + action: cloudStack.lbStickyPolicy.dialog() + } + }, + + 'add-vm': { + label: 'label.add.vms', + addButton: true + } + }, + + tags: cloudStack.api.tags({ resourceType: 'LoadBalancer', contextId: 'multiRule' }), + + add: { + label: 'label.add.vms', + action: function(args) { + args.response.success(); + } + }, + actions: { + edit: { + label: 'label.edit', + action: function(args) { + args.response.success(); + } + }, + destroy: { + label: 'label.action.delete.load.balancer', + action: function(args) { + args.response.success(); + } + } + }, + + itemActions: { + add: { + label: 'label.add.vms.to.lb', + action: function(args) { + args.response.success(); + } + }, + destroy: { + label: 'label.remove.vm.from.lb', + action: function(args) { + args.response.success(); + } + } + }, + dataProvider: function(args) { + args.respons.success({ data: [] }); + } + }); + + return $multi; + } + } + } } } }, From b32d7c026c8d84b0b0c17f75cc4ea73bd932eca5 Mon Sep 17 00:00:00 2001 From: anthony Date: Wed, 23 Jan 2013 11:08:24 -0800 Subject: [PATCH 029/201] CLOUDSTACK-737, allow to add security group enabled networks in security group enabled zone --- .../ConfigurationManagerImpl.java | 10 +++--- .../consoleproxy/ConsoleProxyManagerImpl.java | 31 +++++++++++------- .../SecondaryStorageManagerImpl.java | 32 ++++++++++++------- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index e1aaa5050f9..ef0a7845bf1 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1774,13 +1774,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // check if zone has necessary trafficTypes before enabling try { PhysicalNetwork mgmtPhyNetwork; - if (NetworkType.Advanced == zone.getNetworkType()) { - // zone should have a physical network with public and management traffiType + // zone should have a physical network with management traffiType + mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); + if (NetworkType.Advanced == zone.getNetworkType() && ! zone.isSecurityGroupEnabled() ) { + // advanced zone without SG should have a physical network with public Thpe _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Public); - mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); - } else { - // zone should have a physical network with management traffiType - mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); } try { diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 9a7a46faf3d..421e53f75be 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -687,19 +687,28 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); - TrafficType defaultTrafficType = TrafficType.Public; - if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { - defaultTrafficType = TrafficType.Guest; + NetworkVO defaultNetwork = null; + if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { + List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); + if (networks == null || networks.size() == 0) { + throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc); + } + defaultNetwork = networks.get(0); + } else { + TrafficType defaultTrafficType = TrafficType.Public; + if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { + defaultTrafficType = TrafficType.Guest; + } + List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + + // api should never allow this situation to happen + if (defaultNetworks.size() != 1) { + throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + + defaultTrafficType + " when expect to find 1"); + } + defaultNetwork = defaultNetworks.get(0); } - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); - - if (defaultNetworks.size() != 1) { - throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); - } - - NetworkVO defaultNetwork = defaultNetworks.get(0); - List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork, NetworkOffering.SystemManagementNetwork); List> networks = new ArrayList>(offerings.size() + 1); NicProfile defaultNic = new NicProfile(); diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 3cf9a7ef5a3..c3432863bec 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -538,19 +538,27 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); DataCenter dc = _dcDao.findById(plan.getDataCenterId()); - TrafficType defaultTrafficType = TrafficType.Public; - if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { - defaultTrafficType = TrafficType.Guest; + NetworkVO defaultNetwork = null; + if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { + List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); + if (networks == null || networks.size() == 0) { + throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc); + } + defaultNetwork = networks.get(0); + } else { + TrafficType defaultTrafficType = TrafficType.Public; + + if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { + defaultTrafficType = TrafficType.Guest; + } + List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + // api should never allow this situation to happen + if (defaultNetworks.size() != 1) { + throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + + defaultTrafficType + " when expect to find 1"); + } + defaultNetwork = defaultNetworks.get(0); } - - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); - - //api should never allow this situation to happen - if (defaultNetworks.size() != 1) { - throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); - } - - NetworkVO defaultNetwork = defaultNetworks.get(0); List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork, NetworkOfferingVO.SystemStorageNetwork); List> networks = new ArrayList>(offerings.size() + 1); From 297115cac56d9d211dd8a7ab0413973ed2e2df95 Mon Sep 17 00:00:00 2001 From: anthony Date: Thu, 24 Jan 2013 17:26:51 -0800 Subject: [PATCH 030/201] CLOUDSTACK-737 add xenserver support in UI only XenServer and KVM clusters are allowed in security enabled zone. only shared security enabled networks are allowed in security enabled zone. --- server/src/com/cloud/resource/ResourceManagerImpl.java | 6 ++++++ ui/scripts/zoneWizard.js | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 0ab35dd00a2..4bd62376b38 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -438,6 +438,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + cmd.getHypervisor() + " to a supported "); } + if (zone.isSecurityGroupEnabled()) { + if( hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer ) { + throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone"); + } + } + Cluster.ClusterType clusterType = null; if (cmd.getClusterType() != null && !cmd.getClusterType().isEmpty()) { clusterType = Cluster.ClusterType.valueOf(cmd.getClusterType()); diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index 9b28c327b78..421c5911e4c 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -401,7 +401,6 @@ var nonSupportedHypervisors = {}; if(args.context.zones[0]['network-model'] == "Advanced" && args.context.zones[0]['zone-advanced-sg-enabled'] == "on") { firstOption = "KVM"; - nonSupportedHypervisors["XenServer"] = 1; //to developers: comment this line if you need to test Advanced SG-enabled zone with XenServer hypervisor nonSupportedHypervisors["VMware"] = 1; nonSupportedHypervisors["BareMetal"] = 1; nonSupportedHypervisors["Ovm"] = 1; From 81bce385bfd67a926cc87305aec7b42cb8d8af26 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 15:01:40 -0700 Subject: [PATCH 031/201] Fix typo --- ui/scripts/vpc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index eb3a4b69675..cbb3a6ff1c3 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -457,7 +457,7 @@ } }, dataProvider: function(args) { - args.respons.success({ data: [] }); + args.response.success({ data: [] }); } }); From 612ce62cae8408cdf66aaab339c1cc387b4bf9b1 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 15:33:13 -0700 Subject: [PATCH 032/201] Add tier VM, PF, static NAT links --- ui/modules/vpc/vpc.js | 11 ++++++----- ui/scripts/instances.js | 8 ++++++++ ui/scripts/vpc.js | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 5c93e6cdbe6..64081a8a4d0 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -18,7 +18,9 @@ var elems = { tier: function(args) { var tier = args.tier; - var context = args.context; + var context = $.extend(true, {}, args.context, { + networks: [tier] + }); var dashboardItems = args.dashboardItems; var $tier = $('
    ').addClass('tier-item'); var $header = $('
    ').addClass('header'); @@ -41,9 +43,7 @@ var $detailView = $('
    ').detailView( $.extend(true, {}, cloudStack.vpc.tiers.detailView, { $browser: $browser, - context: $.extend(true, {}, context, { - networks: [tier] - }), + context: context, onActionComplete: function() { $tier.closest('.vpc-network-chart').trigger('reload'); } @@ -153,6 +153,7 @@ dashboard: function(args) { var $dashboard = $('
    ').addClass('dashboard'); var context = args.context; + var tier = context.networks[0]; $(args.dashboardItems).map(function(index, dashboardItem) { var $dashboardItem = $('
    ').addClass('dashboard-item'); @@ -167,7 +168,7 @@ $dashboardItem.click(function() { $('#browser .container').cloudBrowser('addPanel', { - title: dashboardItem.name, + title: tier.name + ' - ' + dashboardItem.name, maximizeIfSelected: true, complete: function($panel) { var section = cloudStack.vpc.sections[id]; diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index c76d843ed6e..31237a8855b 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -204,6 +204,14 @@ affinitygroupid: args.context.affinityGroups[0].id }); } + + if("vpc" in args.context && + "networks" in args.context) { + $.extend(data, { + vpcid: args.context.vpc[0].id, + networkid: args.context.networks[0].id + }); + } $.ajax({ url: createURL('listVirtualMachines'), diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index cbb3a6ff1c3..1e3efb71e2c 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -294,6 +294,26 @@ cloudStack.vpc = { // nTier sections sections: { + tierVMs: function() { + var list = $.extend(true, {}, cloudStack.sections.instances); + + list.listView.actions.add.action.custom = cloudStack.uiCustom.instanceWizard( + $.extend(true, {}, cloudStack.instanceWizard, { + pluginForm: { name: 'vpcTierInstanceWizard' } + }) + ); + + return list; + }, + + tierPortForwarders: function() { + return cloudStack.vpc.ipAddresses.listView(); + }, + + tierStaticNATs: function() { + return cloudStack.vpc.ipAddresses.listView(); + }, + // Internal load balancers tierLoadBalancers: { listView: { From 34d7014c88490c5de009128086f1c273275580cb Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 15:58:55 -0700 Subject: [PATCH 033/201] ACL multi-edit: Fix reorder drag handle --- ui/scripts/ui/widgets/multiEdit.js | 48 ++---------------------------- ui/scripts/vpc.js | 8 ++++- 2 files changed, 10 insertions(+), 46 deletions(-) diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index 0f1515f5aec..14f379fcc2b 100755 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -41,30 +41,6 @@ // Add reorder actions if (reorder) { - var sort = function($tr, action) { - var $listView = $tr.closest('.data-body'); - var viewArgs = $listView.data('view-args'); - var context = $.extend( - true, {}, - options.context - ); - var rowIndex = $tr.closest('.data-body').find('.data-item').size() - ($tr.closest('.data-item').index()); - - context[viewArgs.activeSection] = $tr.data('json-obj'); - - action.action({ - context: context, - index: rowIndex, - response: { - success: function(args) {}, - error: function(args) { - // Move back to previous position - rowActions.moveTo($tr, rowIndex); - } - } - }); - }; - $('
    ').addClass('actions reorder').appendTo($tr).append(function() { var $td = $(this); @@ -99,27 +75,6 @@ }); }); }); - - // Draggable action - var initDraggable = function($dataItem) { - var originalIndex; - - return $dataItem.sortable({ - handle: '.action.moveDrag', - start: function(event, ui) { - originalIndex = ui.item.index(); - }, - stop: function(event, ui) { - $dataItem.closest('.data-body').find('.data-item').each(function() { - sort($(this), reorder.moveDrag); - }); - } - }); - }; - - if (reorder && reorder.moveDrag) { - initDraggable($tr.closest('.data-item')); - } } @@ -872,6 +827,9 @@ $.fn.multiEdit = function(args) { if (reorder) { $('').addClass('reorder').appendTo($thead); $('').addClass('reorder').appendTo($inputForm); + $multi.find('.data-body').sortable({ + handle: '.action.moveDrag' + }); } $.each(args.fields, function(fieldName, field) { diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 1e3efb71e2c..8e393142ec9 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -27,7 +27,13 @@ return hiddenFields; // Returns fields to be hidden }, - reorder: cloudStack.api.actions.sort('updateAclRule', 'multiRule'), + reorder: { + moveDrag: { + action: function(args) { + args.response.success(); + } + } + }, fields: { 'cidrlist': { edit: true, label: 'label.cidr' }, 'protocol': { From 6b406f622088821f53353bc94c81e45ec2ea45c6 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 16:06:09 -0700 Subject: [PATCH 034/201] Lower width of draggable column --- ui/css/cloudstack3.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 7f6df22797e..9fde1b82a37 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -7974,6 +7974,15 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t .multi-edit .header-fields input[type=submit] { } +/* Sortable */ +.multi-edit table tbody tr td.reorder, +.multi-edit table thead tr th.reorder { + width: 30px !important; + min-width: 30px !important; + max-width: 30px !important; +} + + /*Security Rules*/ .security-rules .multi-edit input { width: 69px; From eb34d91afde1d1236a45a4b9088004fb08832430 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 15 May 2013 16:06:20 -0700 Subject: [PATCH 035/201] Multi-edit: Lower font size of table header --- ui/css/cloudstack3.css | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 9fde1b82a37..27841b03ece 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -7925,6 +7925,7 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t width: 87px !important; min-width: 87px !important; max-width: 87px !important; + font-size: 10px; } /** Header fields*/ From b5acb9034f2463c891fa424cd9deaae17501eebc Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Thu, 16 May 2013 11:34:38 -0700 Subject: [PATCH 036/201] CLOUDSTACK-747: UI - Internal LB - implement Add Internal LB action. --- ui/scripts/vpc.js | 66 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 8e393142ec9..7a1c50c10aa 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -323,7 +323,7 @@ // Internal load balancers tierLoadBalancers: { listView: { - id: 'ipAddresses', + id: 'internalLb', fields: { ipaddress: { label: 'label.ip.address' }, type: { label: 'label.type' } @@ -339,30 +339,72 @@ }, actions: { add: { - label: 'Add new LB', + label: 'Add Internal LB', createForm: { - title: 'Add new LB', - desc: 'Please specify the type of load balancer you would like to create.', - fields: { - type: { - label: 'label.type', + title: 'Add Internal LB', + fields: { + name: { label: 'label.name', validation: { required: true } }, + description: { label: 'label.description', validation: { required: false } }, + sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, + sourceport: { label: 'sourceport', validation: { required: true } }, + instanceport: { label: 'instanceport', validation: { required: true } }, + algorithm: { + label: 'label.algorithm', + validation: { required: true }, select: function(args) { args.response.success({ data: [ - { id: 'internal', description: 'Internal' }, - { id: 'public', description: 'Public' } + { id: 'source', description: 'source' }, + { id: 'roundrobin', description: 'roundrobin' }, + { id: 'leastconn', description: 'leastconn' } ] }); } - } + } } }, messages: { notification: function(args) { - return 'Add LB to VPC network'; + return 'Add Internal LB'; } }, - action: function(args) { + action: function(args) { + var data = { + name: args.data.name, + sourceport: args.data.sourceport, + instanceport: args.data.instanceport, + algorithm: args.data.algorithm, + networkid: args.context.networks[0].id, + sourceipaddressnetworkid: args.context.networks[0].id, + scheme: 'Internal' + }; + if(args.data.description != null && args.data.description.length > 0){ + $.extend(data, { + description: args.data.description + }); + } + if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ + $.extend(data, { + sourceipaddress: args.data.sourceipaddress + }); + } + $.ajax({ + url: createURL('createLoadBalancer'), + data: data, + success: function(json){ + var jid = json.createloadbalancerresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + } + } + } + ); + } + }); + args.response.success(); }, notification: { From ff287c10d9c30b19d588e4c5153788a58f97ebf0 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Thu, 16 May 2013 13:45:17 -0700 Subject: [PATCH 037/201] Tier LB UI: Split list view into internal/public --- ui/modules/vpc/vpc.css | 2 +- ui/modules/vpc/vpc.js | 2 +- ui/scripts/vpc.js | 382 ++++++++++++++++++++--------------------- 3 files changed, 192 insertions(+), 194 deletions(-) diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css index a7ef13eadee..92ee80beb05 100644 --- a/ui/modules/vpc/vpc.css +++ b/ui/modules/vpc/vpc.css @@ -140,7 +140,7 @@ } .vpc-network-chart .tier-item .content .dashboard-item .total { - font-size: 28px; + font-size: 17px; /*+placement:shift 7px 5px;*/ position: relative; left: 7px; diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 64081a8a4d0..a3a571eb4c3 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -230,7 +230,7 @@ { id: 'tierLoadBalancers', name: 'Load balancers', - total: 5 + total: '5 Internal
    6 Public' }, { id: 'tierPortForwarders', diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 7a1c50c10aa..57786926686 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -322,214 +322,212 @@ // Internal load balancers tierLoadBalancers: { - listView: { - id: 'internalLb', - fields: { - ipaddress: { label: 'label.ip.address' }, - type: { label: 'label.type' } - }, - dataProvider: function(args) { - args.response.success({ - data: [ - { ipaddress: '10.3.2.1', type: 'Internal' }, - { ipaddress: '10.3.2.3', type: 'Internal' }, - { ipaddress: '10.232.1.4', type: 'Public' } - ] - }); - }, - actions: { - add: { - label: 'Add Internal LB', - createForm: { - title: 'Add Internal LB', - fields: { - name: { label: 'label.name', validation: { required: true } }, - description: { label: 'label.description', validation: { required: false } }, - sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, - sourceport: { label: 'sourceport', validation: { required: true } }, - instanceport: { label: 'instanceport', validation: { required: true } }, - algorithm: { - label: 'label.algorithm', - validation: { required: true }, - select: function(args) { - args.response.success({ - data: [ - { id: 'source', description: 'source' }, - { id: 'roundrobin', description: 'roundrobin' }, - { id: 'leastconn', description: 'leastconn' } - ] + listView: true, + sectionSelect: { + label: 'Select LB type: ' + }, + sections: { + internalLoadBalancers: { + type: 'select', + title: 'Internal LB', + listView: { + id: 'internalLoadBalancers', + fields: { + ipaddress: { label: 'label.ip.address' }, + type: { label: 'label.type' } + }, + dataProvider: function(args) { + args.response.success({ + data: [ + { ipaddress: '10.3.2.1', type: 'Internal' }, + { ipaddress: '10.3.2.3', type: 'Internal' }, + { ipaddress: '10.232.1.4', type: 'Public' } + ] + }); + }, + actions: { + add: { + label: 'Add Internal LB', + createForm: { + title: 'Add Internal LB', + fields: { + name: { label: 'label.name', validation: { required: true } }, + description: { label: 'label.description', validation: { required: false } }, + sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, + sourceport: { label: 'sourceport', validation: { required: true } }, + instanceport: { label: 'instanceport', validation: { required: true } }, + algorithm: { + label: 'label.algorithm', + validation: { required: true }, + select: function(args) { + args.response.success({ + data: [ + { id: 'source', description: 'source' }, + { id: 'roundrobin', description: 'roundrobin' }, + { id: 'leastconn', description: 'leastconn' } + ] + }); + } + } + } + }, + messages: { + notification: function(args) { + return 'Add Internal LB'; + } + }, + action: function(args) { + var data = { + name: args.data.name, + sourceport: args.data.sourceport, + instanceport: args.data.instanceport, + algorithm: args.data.algorithm, + networkid: args.context.networks[0].id, + sourceipaddressnetworkid: args.context.networks[0].id, + scheme: 'Internal' + }; + if(args.data.description != null && args.data.description.length > 0){ + $.extend(data, { + description: args.data.description + }); + } + if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ + $.extend(data, { + sourceipaddress: args.data.sourceipaddress + }); + } + $.ajax({ + url: createURL('createLoadBalancer'), + data: data, + success: function(json){ + var jid = json.createloadbalancerresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + } + } + } + ); + } + }); + + args.response.success(); + }, + notification: { + poll: function(args) { + args.complete({ + data: { + ipaddress: '10.0.3.2', + type: 'Internal' + } }); } - } - } - }, - messages: { - notification: function(args) { - return 'Add Internal LB'; - } - }, - action: function(args) { - var data = { - name: args.data.name, - sourceport: args.data.sourceport, - instanceport: args.data.instanceport, - algorithm: args.data.algorithm, - networkid: args.context.networks[0].id, - sourceipaddressnetworkid: args.context.networks[0].id, - scheme: 'Internal' - }; - if(args.data.description != null && args.data.description.length > 0){ - $.extend(data, { - description: args.data.description - }); - } - if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ - $.extend(data, { - sourceipaddress: args.data.sourceipaddress - }); - } - $.ajax({ - url: createURL('createLoadBalancer'), - data: data, - success: function(json){ - var jid = json.createloadbalancerresponse.jobid; - args.response.success( - {_custom: - {jobId: jid, - getUpdatedItem: function(json) { - return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; - } - } - } - ); } - }); - - args.response.success(); - }, - notification: { - poll: function(args) { - args.complete({ - data: { - ipaddress: '10.0.3.2', - type: 'Internal' - } - }); } } } }, - detailView: { - isMaximized: true, - tabs: { - loadBalancing: { - title: 'label.load.balancing', - custom: function(args) { - var context = args.context; - var $multi = $('
    ').addClass('loadBalancer'); - $multi.multiEdit({ - context: context, - listView: $.extend(true, {}, cloudStack.sections.instances, { - listView: { - fields: { - name: { label: 'label.name' }, - displayname: { label: 'label.display.name' }, - zonename: { label: 'label.zone.name' }, - state: { - label: 'label.state', - indicator: { - 'Running': 'on', - 'Stopped': 'off', - 'Destroyed': 'off', - 'Error': 'off' - } - } - }, - filters: false, - dataProvider: function(args) { - args.response.success({ data: [] }); - } - } - }), - - multipleAdd: true, - - fields: { - 'name': { edit: true, label: 'label.name', isEditable: true }, - 'publicport': { edit: true, label: 'label.public.port' }, - 'privateport': { edit: true, label: 'label.private.port' }, - 'algorithm': { + publicLoadBalancers: { + type: 'select', + title: 'Public LB', + listView: { + id: 'publicLoadBalancers', + fields: { + ipaddress: { label: 'label.ip.address' }, + type: { label: 'label.type' } + }, + dataProvider: function(args) { + args.response.success({ + data: [ + { ipaddress: '10.3.2.1', type: 'Internal' }, + { ipaddress: '10.3.2.3', type: 'Internal' }, + { ipaddress: '10.232.1.4', type: 'Public' } + ] + }); + }, + actions: { + add: { + label: 'Add Public LB', + createForm: { + title: 'Add Public LB', + fields: { + name: { label: 'label.name', validation: { required: true } }, + description: { label: 'label.description', validation: { required: false } }, + sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, + sourceport: { label: 'sourceport', validation: { required: true } }, + instanceport: { label: 'instanceport', validation: { required: true } }, + algorithm: { label: 'label.algorithm', - isEditable: true, + validation: { required: true }, select: function(args) { args.response.success({ data: [ - { id: 'roundrobin', name: 'roundrobin', description: _l('label.round.robin') }, - { id: 'leastconn', name: 'leastconn', description: _l('label.least.connections') }, - { id: 'source', name: 'source', description: _l('label.source') } + { id: 'source', description: 'source' }, + { id: 'roundrobin', description: 'roundrobin' }, + { id: 'leastconn', description: 'leastconn' } ] }); } - }, - - 'sticky': { - label: 'label.stickiness', - custom: { - buttonLabel: 'label.configure', - action: cloudStack.lbStickyPolicy.dialog() - } - }, - - 'add-vm': { - label: 'label.add.vms', - addButton: true - } - }, - - tags: cloudStack.api.tags({ resourceType: 'LoadBalancer', contextId: 'multiRule' }), - - add: { - label: 'label.add.vms', - action: function(args) { - args.response.success(); - } - }, - actions: { - edit: { - label: 'label.edit', - action: function(args) { - args.response.success(); - } - }, - destroy: { - label: 'label.action.delete.load.balancer', - action: function(args) { - args.response.success(); - } - } - }, - - itemActions: { - add: { - label: 'label.add.vms.to.lb', - action: function(args) { - args.response.success(); - } - }, - destroy: { - label: 'label.remove.vm.from.lb', - action: function(args) { - args.response.success(); - } - } - }, - dataProvider: function(args) { - args.response.success({ data: [] }); + } } - }); - - return $multi; + }, + messages: { + notification: function(args) { + return 'Add Public LB'; + } + }, + action: function(args) { + var data = { + name: args.data.name, + sourceport: args.data.sourceport, + instanceport: args.data.instanceport, + algorithm: args.data.algorithm, + networkid: args.context.networks[0].id, + sourceipaddressnetworkid: args.context.networks[0].id, + scheme: 'Public' + }; + if(args.data.description != null && args.data.description.length > 0){ + $.extend(data, { + description: args.data.description + }); + } + if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ + $.extend(data, { + sourceipaddress: args.data.sourceipaddress + }); + } + $.ajax({ + url: createURL('createLoadBalancer'), + data: data, + success: function(json){ + var jid = json.createloadbalancerresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + } + } + } + ); + } + }); + + args.response.success(); + }, + notification: { + poll: function(args) { + args.complete({ + data: { + ipaddress: '10.0.3.2', + type: 'Internal' + } + }); + } + } } } } From 7aaff0cfed028b853f6a72fc7d1b2bf589cbd500 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Thu, 16 May 2013 13:46:37 -0700 Subject: [PATCH 038/201] Fix typo --- ui/scripts/vpc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 57786926686..df4664be3c1 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -324,7 +324,7 @@ tierLoadBalancers: { listView: true, sectionSelect: { - label: 'Select LB type: ' + label: 'Select LB type' }, sections: { internalLoadBalancers: { From 93e046a24ca22baf059ec141619dee6d2d6cb1a9 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 17 May 2013 10:12:49 -0700 Subject: [PATCH 039/201] Fix CSS styling for multi-line VPC dashboard items --- ui/modules/vpc/vpc.css | 6 +++++- ui/modules/vpc/vpc.js | 12 ++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css index 92ee80beb05..51c3f7e05bd 100644 --- a/ui/modules/vpc/vpc.css +++ b/ui/modules/vpc/vpc.css @@ -140,7 +140,7 @@ } .vpc-network-chart .tier-item .content .dashboard-item .total { - font-size: 17px; + font-size: 30px; /*+placement:shift 7px 5px;*/ position: relative; left: 7px; @@ -154,6 +154,10 @@ text-shadow: 0px 1px 1px #FFFFFF; } +.vpc-network-chart .tier-item .content .dashboard-item .total.multiline { + font-size: 14px; +} + .vpc-network-chart .tier-item .content .dashboard-item .name { font-size: 11px; text-transform: uppercase; diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index a3a571eb4c3..f3cdaf040d5 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -162,7 +162,15 @@ var id = dashboardItem.id; $name.find('span').html(dashboardItem.name); - $total.find('span').html(dashboardItem.total); + + + if (dashboardItem.totalMultiLine) { + $total.find('span').html(dashboardItem.totalMultiLine); + $total.addClass('multiline'); + } else { + $total.find('span').html(dashboardItem.total); + } + $dashboardItem.append($total, $name); $dashboardItem.appendTo($dashboard); @@ -230,7 +238,7 @@ { id: 'tierLoadBalancers', name: 'Load balancers', - total: '5 Internal
    6 Public' + totalMultiLine: '5 Internal
    6 Public' }, { id: 'tierPortForwarders', From 981b5ddd1be845b3f73ce69325652cadabb72807 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 20 May 2013 23:42:55 +0530 Subject: [PATCH 040/201] ACL DENY RULES UI-API Integration --- ui/css/cloudstack3.css | 6 +- ui/scripts/sharedFunctions.js | 2 +- ui/scripts/vpc.js | 178 +++++++++++++++++++++++++++++----- 3 files changed, 159 insertions(+), 27 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 27841b03ece..549db3771ac 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -11828,13 +11828,15 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it .downloadVolume .icon, .downloadTemplate .icon, -.downloadISO .icon { +.downloadISO .icon, +.replaceacllist .icon { background-position: -35px -125px; } .downloadVolume:hover .icon, .downloadTemplate:hover .icon, -.downloadISO:hover .icon { +.downloadISO:hover .icon, +.replaceacllist:hover .icon { background-position: -35px -707px; } diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 035299059c2..d87f0dcb0ae 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -276,7 +276,7 @@ cloudStack.actionFilter = { guestNetwork: function(args) { var jsonObj = args.context.item; var allowedActions = []; - + allowedActions.push('replaceacllist'); if(jsonObj.type == 'Isolated') { allowedActions.push('edit'); //only Isolated network is allowed to upgrade to a different network offering (Shared network is not allowed to) allowedActions.push('restart'); diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index df4664be3c1..6ea41c99b6b 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -189,8 +189,7 @@ $.ajax({ url: createURL('createNetworkACL'), data: $.extend(args.data, { - networkid: args.context.networks ? - args.context.networks[0].id : args.data.networkid + aclid: args.context.aclLists[0].id }), dataType: 'json', success: function(data) { @@ -198,10 +197,11 @@ _custom: { jobId: data.createnetworkaclresponse.jobid, getUpdatedItem: function(json) { - var networkName = $multi.find('select[name=networkid] option[value=' + args.data.networkid + ']').html(); - var data = $.extend(json.queryasyncjobresultresponse.jobresult.networkacl, { + //var networkName = $multi.find('select[name=networkid] option[value=' + args.data.networkid + ']').html(); + /* var data = $.extend(json.queryasyncjobresultresponse.jobresult.networkacl, { networkid: networkName - }); + });*/ + var data = json.queryasyncjobresultresponse.jobresult.networkacl; var aclRules = $multi.data('acl-rules'); aclRules.push(data); @@ -551,34 +551,88 @@ id: 'aclLists', fields: { name: { label: 'label.name' }, - total: { label: 'label.total' } + id: { label: 'id' } }, dataProvider: function(args) { - args.response.success({ - data: [ - { name: 'ACL list 1', total: 3 }, - { name: 'ACL list 2', total: 2 } - ] - }); - }, + $.ajax({ + + url:createURL('listNetworkACLLists&vpc_id=' + args.context.vpc[0].id), + success:function(json){ + var items = json.listnetworkacllistsresponse.networkacllist; + + args.response.success({ + data:items + }); + } + }); + }, + + actions:{ + add:{ + label:'Add ACL List', + createForm:{ + label: 'Add ACL List', + fields:{ + name:{label:'ACL List Name',validation:{required:true}}, + description:{label:'Description',validation:{required:true}} + } + }, + messages: { + notification: function(args) { + return 'Add Network ACL List'; + } + }, + action:function(args){ + var data = { + name:args.data.name, + description:args.data.description + + }; + + $.ajax({ + url:createURL('createNetworkACLList&vpcid='+ args.context.vpc[0].id), + data:data, + success:function(json){ + var items = json.createnetworkacllistresponse; + args.response.success({ + data:items + }); + } + }); + } + } + }, + detailView: { isMaximized: true, tabs: { - details: { + /* details: { + title: 'label.details', fields: [ { - name: { label: 'label.name', isEditable: true } + name: { label: 'label.name', isEditable: true }, + id: {label:'id'} } + ], dataProvider: function(args) { - args.response.success({ data: args.context.aclLists[0] }); - } - }, + $.ajax({ + url:createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), + success:function(json){ + var items = json.listnetworkaclsresponse.networkacl; + args.response.success({ + data:items + }); + } + }); + } + + },*/ aclRules: { - title: 'label.acl.rules', + title: 'ACL List Rules', custom: function(args) { return $('
    ').multiEdit($.extend(true, {}, aclMultiEdit, { context: args.context, @@ -586,9 +640,14 @@ networkid: false }, dataProvider: function(args) { + $.ajax({ + url:createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), + success:function(json){ + var items = json.listnetworkaclsresponse.networkacl; + args.response.success({ - data: [ - { + data:items + /* { cidrlist: '10.1.1.0/24', protocol: 'TCP', startport: 22, endport: 22, @@ -602,9 +661,11 @@ networkid: 0, trafficType: 'Ingress' } - ] + ]*/ }); - } + } + }); + } })); } } @@ -2232,7 +2293,76 @@ notification: { poll: pollAsyncJobResult } - } + }, + + replaceacllist:{ + + label:'Replace ACL List', + createForm:{ + title:'Replace ACL List', + label:'Replace ACL List', + fields:{ + aclid:{ + label:'ACL', + select:function(args){ + $.ajax({ + url: createURL('listNetworkACLLists'), + dataType: 'json', + async: true, + success: function(json) { + var objs = json.listnetworkacllistsresponse.networkacllist; + var items = []; + $(objs).each(function() { + + items.push({id: this.id, description: this.name}); + }); + args.response.success({data: items}); + } + }); + } + } + } + }, + action: function(args) { + $.ajax({ + url: createURL("replaceNetworkACLList&networkid=" + args.context.networks[0].id + "&aclid=" + args.data.aclid ), + dataType: "json", + success: function(json) { + var jid = json.replacenetworkacllistresponse.jobid; + args.response.success( + + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + var item = json.queryasyncjobresultresponse.jobresult.aclid; + return {data:item}; + } + } + } + + ) + }, + + error:function(json){ + + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + }, + + messages: { + confirm: function(args) { + return 'Do you want to replace the ACL with a new one ?'; + }, + notification: function(args) { + return 'ACL replaced'; + } + } + } }, tabFilter: function(args) { From a1614a5f8f7c865e804706bd100f158e6abb5eaa Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 21 May 2013 01:25:10 +0530 Subject: [PATCH 041/201] ACL DENY RULES Network ACL List Detail View --- ui/scripts/vpc.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 6ea41c99b6b..08cf82dda61 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -551,6 +551,7 @@ id: 'aclLists', fields: { name: { label: 'label.name' }, + description: {label:'Description'}, id: { label: 'id' } }, dataProvider: function(args) { @@ -607,30 +608,27 @@ detailView: { isMaximized: true, tabs: { - /* details: { + details: { + title: 'label.details', fields: [ { name: { label: 'label.name', isEditable: true }, - id: {label:'id'} + description: {label:'Description'}, + id:{label:'id'} } - + ], dataProvider: function(args) { - $.ajax({ - url:createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), - success:function(json){ - var items = json.listnetworkaclsresponse.networkacl; - args.response.success({ - data:items - }); - } - }); - } - - },*/ + var items = args.context.aclLists[0]; + args.response.success({ + data: items + }); + } + }, + aclRules: { title: 'ACL List Rules', custom: function(args) { From 034c21b6fc173deeb003d1ef2473c4c47c5bad4a Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 20 May 2013 13:32:46 -0700 Subject: [PATCH 042/201] ACL multi-edit: add 'action' field to specify rule as allow/deny --- ui/scripts/vpc.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 08cf82dda61..ce2334ce608 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -36,6 +36,17 @@ }, fields: { 'cidrlist': { edit: true, label: 'label.cidr' }, + action: { + label: 'Action', + select: function(args) { + args.response.success({ + data: [ + { name: 'Allow', description: 'Allow' }, + { name: 'Deny', description: 'Deny' } + ] + }); + } + }, 'protocol': { label: 'label.protocol', select: function(args) { From 9e24af77b9537d2e2126f2dde3e0b6a6cb871d60 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 20 May 2013 13:34:37 -0700 Subject: [PATCH 043/201] CLOUDSTACK-747: internalLb in VPC - UI - create network offering - system offering dropdown is for router only. Change its variable name to be more intuitive. --- ui/scripts/configuration.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 9a08c4c56b1..e3421a380ef 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -1122,7 +1122,7 @@ title: 'label.add.network.offering', preFilter: function(args) { var $availability = args.$form.find('.form-item[rel=availability]'); - var $serviceOfferingId = args.$form.find('.form-item[rel=serviceOfferingId]'); + var $systemOfferingForRouter = args.$form.find('.form-item[rel=systemOfferingForRouter]'); var $conservemode = args.$form.find('.form-item[rel=conservemode]'); var $serviceSourceNatRedundantRouterCapabilityCheckbox = args.$form.find('.form-item[rel="service.SourceNat.redundantRouterCapabilityCheckbox"]'); var hasAdvancedZones = false; @@ -1185,10 +1185,10 @@ } }); if(havingVirtualRouterForAtLeastOneService == true) { - $serviceOfferingId.css('display', 'inline-block'); + $systemOfferingForRouter.css('display', 'inline-block'); } else { - $serviceOfferingId.hide(); + $systemOfferingForRouter.hide(); } @@ -1569,8 +1569,8 @@ }, //show or hide upon checked services and selected providers above (begin) - serviceOfferingId: { - label: 'label.system.offering', + systemOfferingForRouter: { + label: 'System Offering for Router', docID: 'helpNetworkOfferingSystemOffering', select: function(args) { $.ajax({ @@ -1829,8 +1829,8 @@ if(args.$form.find('.form-item[rel=availability]').css("display") == "none") inputData['availability'] = 'Optional'; - if(args.$form.find('.form-item[rel=serviceOfferingId]').css("display") == "none") - delete inputData.serviceOfferingId; + if(args.$form.find('.form-item[rel=systemOfferingForRouter]').css("display") == "none") + delete inputData.systemOfferingForRouter; inputData['traffictype'] = 'GUEST'; //traffic type dropdown has been removed since it has only one option ('Guest'). Hardcode traffic type value here. From bd764cc581a47e213350ef5749ae523f5b0398c2 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 20 May 2013 13:55:43 -0700 Subject: [PATCH 044/201] Pass dashboard data via dataProvider --- ui/modules/vpc/vpc.js | 58 ++++++------------------------------------- ui/scripts/vpc.js | 51 ++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index f3cdaf040d5..3c44a4cabca 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -234,28 +234,7 @@ var $tier = elems.tier({ context: context, tier: tier, - dashboardItems: [ - { - id: 'tierLoadBalancers', - name: 'Load balancers', - totalMultiLine: '5 Internal
    6 Public' - }, - { - id: 'tierPortForwarders', - name: 'Port forwarders', - total: 4 - }, - { - id: 'tierStaticNATs', - name: 'Static NATs', - total: 3 - }, - { - id: 'tierVMs', - name: 'Virtual Machines', - total: 300 - } - ] + dashboardItems: tier._dashboardItems }); $tier.appendTo($tiers); @@ -271,37 +250,16 @@ if (args.complete) { args.complete($chart); } + + // Router + $router = elems.router({ + context: context, + dashboardItems: data.routerDashboard + }).appendTo($chart); } - } + } }); - // Router - $router = elems.router({ - context: context, - dashboardItems: [ - { - id: 'privateGateways', - name: 'Private gateways', - total: 1 - }, - { - id: 'publicIPs', - name: 'Public IP addresses', - total: 2 - }, - { - id: 'siteToSiteVPNs', - name: 'Site-to-site VPNs', - total: 3 - }, - { - id: 'networkACLLists', - name: 'Network ACL lists', - total: 2 - } - ] - }).appendTo($chart); - $chart.bind('reload', function() { chart({ complete: function($newChart) { diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index ce2334ce608..a081ab85667 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -2998,7 +2998,56 @@ }); } } - args.response.success({ tiers: networks }); + args.response.success({ + routerDashboard: [ + { + id: 'privateGateways', + name: 'Private gateways', + total: 0 + }, + { + id: 'publicIPs', + name: 'Public IP addresses', + total: 0 + }, + { + id: 'siteToSiteVPNs', + name: 'Site-to-site VPNs', + total: 0 + }, + { + id: 'networkACLLists', + name: 'Network ACL lists', + total: 0 + } + ], + tiers: $(networks).map(function(index, tier) { + return $.extend(tier, { + _dashboardItems: [ + { + id: 'tierLoadBalancers', + name: 'Load balancers', + totalMultiLine: '0 Internal
    0 Public' + }, + { + id: 'tierPortForwarders', + name: 'Port forwarders', + total: 0 + }, + { + id: 'tierStaticNATs', + name: 'Static NATs', + total: 0 + }, + { + id: 'tierVMs', + name: 'Virtual Machines', + total: 0 + } + ] + }); + }) + }); } }); } From 6b7098c990c014ac88ae2981c3c8f20a2a536239 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Mon, 20 May 2013 14:10:52 -0700 Subject: [PATCH 045/201] Add network ACL item: Fix add action --- ui/scripts/vpc.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index a081ab85667..710265c8d0f 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -208,15 +208,6 @@ _custom: { jobId: data.createnetworkaclresponse.jobid, getUpdatedItem: function(json) { - //var networkName = $multi.find('select[name=networkid] option[value=' + args.data.networkid + ']').html(); - /* var data = $.extend(json.queryasyncjobresultresponse.jobresult.networkacl, { - networkid: networkName - });*/ - var data = json.queryasyncjobresultresponse.jobresult.networkacl; - var aclRules = $multi.data('acl-rules'); - - aclRules.push(data); - $multi.data('acl-rules', aclRules); $(window).trigger('cloudStack.fullRefresh'); return data; From 933060dfeb88e5032da813b2fea12027757693a6 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 20 May 2013 19:17:21 -0700 Subject: [PATCH 046/201] CLOUDSTACK-747: internalLb in VPC - UI - create network offering - add LB Type dropdodwn which is shown when VPC is checked and LB service is checked, hidden otherwise. LB Type (publicLb, internalLb) will determine the options in LB Provider dropdown. --- ui/scripts/configuration.js | 85 +++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index e3421a380ef..058f44097b8 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -1122,6 +1122,7 @@ title: 'label.add.network.offering', preFilter: function(args) { var $availability = args.$form.find('.form-item[rel=availability]'); + var $lbType = args.$form.find('.form-item[rel=lbType]'); var $systemOfferingForRouter = args.$form.find('.form-item[rel=systemOfferingForRouter]'); var $conservemode = args.$form.find('.form-item[rel=conservemode]'); var $serviceSourceNatRedundantRouterCapabilityCheckbox = args.$form.find('.form-item[rel="service.SourceNat.redundantRouterCapabilityCheckbox"]'); @@ -1147,18 +1148,18 @@ //check whether to show or hide availability field var $sourceNATField = args.$form.find('input[name=\"service.SourceNat.isEnabled\"]'); var $guestTypeField = args.$form.find('select[name=guestIpType]'); - + + var $useVpc = args.$form.find('.form-item[rel=\"useVpc\"]'); + var $useVpcCb = $useVpc.find("input[type=checkbox]"); if($guestTypeField.val() == 'Shared') { //Shared network offering - args.$form.find('.form-item[rel=\"useVpc\"]').hide(); - - var $useVpcCb = args.$form.find('.form-item[rel=\"useVpc\"]').find("input[type=checkbox]"); + $useVpc.hide(); if($useVpcCb.is(':checked')) { //if useVpc is checked, $useVpcCb.removeAttr("checked"); //remove "checked" attribute in useVpc $useVpcCb.trigger("click"); //trigger useVpc.onChange() } } else { //Isolated network offering - args.$form.find('.form-item[rel=\"useVpc\"]').css('display', 'inline-block'); + $useVpc.css('display', 'inline-block'); } @@ -1170,7 +1171,14 @@ $availability.hide(); } - + //when useVpc is checked and service.Lb.isEnabled is checked + if($useVpcCb.is(':checked') && $("input[name='service.Lb.isEnabled']").is(":checked") == true) { + $lbType.css('display', 'inline-block'); + } + else { + $lbType.hide(); + } + //when service(s) has Virtual Router as provider..... var havingVirtualRouterForAtLeastOneService = false; $(serviceCheckboxNames).each(function(){ @@ -1427,7 +1435,7 @@ label: 'VPC', docID: 'helpNetworkOfferingVPC', isBoolean: true, - onChange: function(args) { + onChange: function(args) { var $checkbox = args.$checkbox; var $selects = $checkbox.closest('form').find('.dynamic-input select'); var $vpcOptions = $selects.find('option[value=VpcVirtualRouter]'); @@ -1444,7 +1452,67 @@ } } }, - + + lbType: { //only shown when VPC is checked and LB service is checked + label: 'Load Balancer Type', + isHidden: true, + select: function(args) { + args.response.success({data: [ + {id: 'publicLb', description: 'Public LB'}, + {id: 'internalLb', description: 'Internal LB'} + ]}); + + args.$select.change(function() { + if($(this).is(':visible') == false) + return; //if lbType is not visible, do nothing. + + var $lbProvider = $(this).closest('form').find('.form-item[rel=\"service.Lb.provider\"]').find('select'); + var $lbProviderOptions = $lbProvider.find('option'); + + if($(this).val() == 'publicLb') { //disable all providers except the ones in lbProviderMap.publicLb.vpc => ["VpcVirtualRouter", "Netscaler"] + for(var i = 0; i < $lbProviderOptions.length; i++ ) { + var $option = $lbProviderOptions.eq(i); + var supportedProviders = lbProviderMap.publicLb.vpc; + var thisOpionIsSupported = false; + for(var k = 0; k < supportedProviders.length; k++ ) { + if($option.val() == supportedProviders[k]) { + thisOpionIsSupported = true; + break; + } + } + if(thisOpionIsSupported == true) { + $option.attr('disabled', false); + } + else { + $option.attr('disabled', true); + } + } + } + else if($(this).val() == 'internalLb') { //disable all providers except the ones in lbProviderMap.internalLb.vpc => ["InternalLbVm"] + for(var i = 0; i < $lbProviderOptions.length; i++ ) { + var $option = $lbProviderOptions.eq(i); + var supportedProviders = lbProviderMap.internalLb.vpc; + var thisOpionIsSupported = false; + for(var k = 0; k < supportedProviders.length; k++ ) { + if($option.val() == supportedProviders[k]) { + thisOpionIsSupported = true; + break; + } + } + if(thisOpionIsSupported == true) { + $option.attr('disabled', false); + } + else { + $option.attr('disabled', true); + } + } + } + + $lbProvider.val($lbProvider.find('option:first')); + }); + } + }, + supportedServices: { label: 'label.supported.services', @@ -1571,6 +1639,7 @@ //show or hide upon checked services and selected providers above (begin) systemOfferingForRouter: { label: 'System Offering for Router', + isHidden: true, docID: 'helpNetworkOfferingSystemOffering', select: function(args) { $.ajax({ From e5e41b0f454059511ea97a534331db7213bef67e Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 21 May 2013 16:35:14 +0530 Subject: [PATCH 047/201] Remove ACL List action item --- ui/scripts/vpc.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 710265c8d0f..2c954200b96 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -609,6 +609,44 @@ detailView: { isMaximized: true, + actions:{ + deleteacllist:{ + label:'Delete ACL List', + messages: { + confirm: function(args) { + return 'Are you sure you want to delete this ACL list ?'; + }, + notification: function(args) { + return 'Delete ACL list'; + } + }, + action:function(args){ + $.ajax({ + url:createURL('deleteNetworkACLList&id=' + args.context.aclLists[0].id), + success:function(json){ + var jid = json.deletenetworkacllistresponse.jobid; + args.response.success( + {_custom: + { jobId: jid + } + } + ); + + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); + + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + + } + }, + + tabs: { details: { From e6382b1896692e4e76afa7f7a7f7a2c304958006 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 21 May 2013 22:15:15 +0530 Subject: [PATCH 048/201] Delete ACL list filter and css --- ui/css/cloudstack3.css | 6 ++++-- ui/scripts/vpc.js | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 549db3771ac..16584537905 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -11736,13 +11736,15 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it .destroy .icon, .remove .icon, .delete .icon, -.decline .icon { +.decline .icon, +.deleteacllist .icon { background-position: 1px -92px; } .destroy:hover .icon, .remove:hover .icon, -.delete:hover .icon { +.delete:hover .icon, +.deleteacllist:hover .icon { background-position: 1px -674px; } diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 2c954200b96..fa5c0a56c8e 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -663,7 +663,16 @@ dataProvider: function(args) { var items = args.context.aclLists[0]; args.response.success({ - data: items + data: items, + actionFilter: function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("deleteacllist"); + + } + return allowedActions; + } + }); } From ccf1ebc26b3aa361ceba837e669ab60053c0c0de Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 21 May 2013 10:57:12 -0700 Subject: [PATCH 049/201] CLOUDSTACK-747: internalLb in VPC - UI - create network offering - when VPC checkbox is checked, enable provider InternalLbVm, VpcVirtualRouter, Netscaler. When VPC checkbox is unchecked, disable provider InternalLbVm, VpcVirtualRouter. --- ui/scripts/configuration.js | 41 ++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 058f44097b8..7485898dc19 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -1436,20 +1436,37 @@ docID: 'helpNetworkOfferingVPC', isBoolean: true, onChange: function(args) { - var $checkbox = args.$checkbox; - var $selects = $checkbox.closest('form').find('.dynamic-input select'); - var $vpcOptions = $selects.find('option[value=VpcVirtualRouter]'); + var $vpc = args.$checkbox; + var $providers = $vpc.closest('form').find('.dynamic-input select'); + var $optionsOfProviders = $providers.find('option'); - if ($checkbox.is(':checked')) { - $vpcOptions.siblings().attr('disabled', true); - $selects.val('VpcVirtualRouter'); - } else { - $vpcOptions.siblings().attr('disabled', false); - $vpcOptions.attr('disabled', true); - $selects.each(function() { - $(this).val($(this).find('option:first')); - }); + //p.s. Netscaler is supported in both vpc and non-vpc + + if ($vpc.is(':checked')) { //*** vpc *** + $optionsOfProviders.each(function(index) { + if($(this).val() == 'InternalLbVm' || $(this).val() == 'VpcVirtualRouter' || $(this).val() == 'Netscaler') { + $(this).attr('disabled', false); + } + else { + $(this).attr('disabled', true); + } + }); + } + else { //*** non-vpc *** + $optionsOfProviders.each(function(index) { + if($(this).val() == 'InternalLbVm' || $(this).val() == 'VpcVirtualRouter') { + $(this).attr('disabled', true); + } + else { + $(this).attr('disabled', false); + } + }); } + + $providers.each(function() { + $(this).val($(this).find('option:first')); + }); + } }, From 75df90663f72bb0b8c9c8de84de8684cb96a1ba6 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 21 May 2013 11:37:12 -0700 Subject: [PATCH 050/201] CLOUDSTACK-747: internalLb in VPC - UI - create network offering - when Lb service is checked and LB provider is InternalLbVm, pass capability type as lbSchemes and capability value as internal. --- ui/scripts/configuration.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 7485898dc19..92c3d00478e 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -1834,7 +1834,13 @@ inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'associatePublicIP'; inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = true; //because this checkbox's value == "on" serviceCapabilityIndex++; - } + } + else if((key == 'service.Lb.provider') && ("Lb" in serviceProviderMap) && (serviceProviderMap.Lb == "InternalLbVm")) { + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].service'] = 'lb'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'lbSchemes'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = 'internal'; + serviceCapabilityIndex++; + } } else if (value != '') { // Normal data inputData[key] = value; From 0eceb0da603dfb93df9314b6f034ca32d45a14b6 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 21 May 2013 11:59:03 -0700 Subject: [PATCH 051/201] CLOUDSTACK-747: UI - create network offering - default sourceNat type as per account instead of per zone. --- ui/scripts/configuration.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 92c3d00478e..5762e648103 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -1702,9 +1702,9 @@ dependsOn: 'service.SourceNat.isEnabled', select: function(args) { args.response.success({ - data: [ - { id: 'perzone', description: 'Per zone'}, - { id: 'peraccount', description: 'Per account'} + data: [ + { id: 'peraccount', description: 'Per account'}, + { id: 'perzone', description: 'Per zone'} ] }); } From 451c83c998a96f908a04d3329e1dc695c64849e8 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 12:52:55 -0700 Subject: [PATCH 052/201] Fix listView add/replace row for VPC section --- ui/scripts/ui/widgets/listView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 0d5ef6fc751..031874dff1f 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -1873,7 +1873,7 @@ if (!options) options = {}; var viewArgs = listView.data('view-args'); - var listViewArgs = viewArgs.listView ? viewArgs.listView : viewArgs; + var listViewArgs = $.isPlainObject(viewArgs.listView) ? viewArgs.listView : viewArgs; var targetArgs = listViewArgs.activeSection ? listViewArgs.sections[ listViewArgs.activeSection ].listView : listViewArgs; @@ -1903,7 +1903,7 @@ var $newRow; var $listView = $row.closest('.list-view'); var viewArgs = $listView.data('view-args'); - var listViewArgs = viewArgs.listView ? viewArgs.listView : viewArgs; + var listViewArgs = $.isPlainObject(viewArgs.listView) ? viewArgs.listView : viewArgs; var targetArgs = listViewArgs.activeSection ? listViewArgs.sections[ listViewArgs.activeSection ].listView : listViewArgs; From 9fff2c4a666cfb0a330c4385812584c91fa49188 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 12:54:07 -0700 Subject: [PATCH 053/201] Add VM total to dashboard --- ui/scripts/vpc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index fa5c0a56c8e..9cef91a0793 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3080,7 +3080,7 @@ { id: 'tierVMs', name: 'Virtual Machines', - total: 0 + total: $.isArray(tier.virtualMachines) ? tier.virtualMachines.length : 0 } ] }); From c89ca6a92f0eb9e30dbdaccca2b97ccad32f0a01 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 21 May 2013 13:15:09 -0700 Subject: [PATCH 054/201] CLOUDSTACK-747: internalLb in VPC - populate listView of internal LB. --- ui/scripts/vpc.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 9cef91a0793..d100aeb602b 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -335,17 +335,21 @@ listView: { id: 'internalLoadBalancers', fields: { - ipaddress: { label: 'label.ip.address' }, - type: { label: 'label.type' } + name: { label: 'label.name' }, + sourceipaddress: { label: 'Source IP Address' } }, - dataProvider: function(args) { - args.response.success({ - data: [ - { ipaddress: '10.3.2.1', type: 'Internal' }, - { ipaddress: '10.3.2.3', type: 'Internal' }, - { ipaddress: '10.232.1.4', type: 'Public' } - ] - }); + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + networkid: args.context.networks[0].id + }, + success: function(json) { + var items = json.listloadbalancerssresponse.loadbalancer; + args.response.success({ data: items }); + + } + }); }, actions: { add: { From 41f9a12d38b7f405a1424089dbdd640f9dd3651e Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 21 May 2013 13:48:27 -0700 Subject: [PATCH 055/201] CLOUDSTACK-747: internalLb in VPC - populate detailView of internal LB. --- ui/scripts/vpc.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index d100aeb602b..7778a2d0d6b 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -432,7 +432,41 @@ } } } - } + }, + + detailView: { + name: 'Internal Lb details', + actions: { + //assignVm: { + + //} + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + id: { label: 'label.id' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item }); + } + }); + } + } + } + } } }, From dfa93b52a894930d847b4f39b69be990f2aacd4b Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 15:07:21 -0700 Subject: [PATCH 056/201] Detail view actions: Add support listView selection Adds a new dialog 'cloudStack.dialog.listView' -- Supports displaying a list view in a popup dialog, for selecting items for an action (i.e., selecting VMs for an LB rule). Arguments are a list view object and the 'type' of selection: either 'checkbox' or 'radio' Example: detailView: { name: 'Internal Lb details', actions: { assignVm: { label: 'Assign VMs to LB', messages: { notification: function(args) { return 'Assign VM to internal LB rule'; } }, listView: $.extend(true, {}, cloudStack.sections.instances.listView, { type: 'checkbox', filters: false }), action: function(args) { args.response.success(); }, notification: { poll: function(args) { args.complete(); } } } }, ... } --- ui/scripts/ui/dialog.js | 92 ++++++++++++++++++++++++++++- ui/scripts/ui/widgets/detailView.js | 16 ++++- 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/ui/scripts/ui/dialog.js b/ui/scripts/ui/dialog.js index bb372fbf3d6..45f928e38a9 100644 --- a/ui/scripts/ui/dialog.js +++ b/ui/scripts/ui/dialog.js @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -(function($, cloudStack) { +(function($, cloudStack, _l) { cloudStack.dialog = { /** * Error message form @@ -506,6 +506,94 @@ } }, + // Dialog with list view selector + listView: function(args) { + var listView = args.listView; + var after = args.after; + var context = args.context; + var $listView = $('
    '); + + listView.actions = { + select: { + label: _l('label.select.instance'), + type: listView.type, + action: { + uiCustom: function(args) { + var $item = args.$item; + var $input = $item.find('td.actions input:visible'); + + if ($input.attr('type') == 'checkbox') { + if ($input.is(':checked')) + $item.addClass('multi-edit-selected'); + else + $item.removeClass('multi-edit-selected'); + } else { + $item.siblings().removeClass('multi-edit-selected'); + $item.addClass('multi-edit-selected'); + } + } + } + } + }; + + // Init list view + $listView = $('
    ').listView({ + context: context, + uiCustom: true, + listView: listView + }); + + // Change action label + $listView.find('th.actions').html(_l('label.select')); + + $listView.dialog({ + dialogClass: 'multi-edit-add-list panel', + width: 825, + title: _l('Select VM'), + buttons: [ + { + text: _l('label.apply'), + 'class': 'ok', + click: function() { + if (!$listView.find( + 'input[type=radio]:checked, input[type=checkbox]:checked' + ).size()) { + cloudStack.dialog.notice({ message: _l('message.select.instance')}); + + return false; + } + + after({ + context: $.extend(true, {}, context, { + instances: $listView.find('tr.multi-edit-selected').map(function(index, row) { + var $row = $(row); + + return $row.data('json-obj'); + }) + }) + }); + + $listView.remove(); + + $('div.overlay').remove(); + } + }, + { + text: _l('label.cancel'), + 'class': 'cancel', + click: function() { + $listView.fadeOut(function() { + $listView.remove(); + }); + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); + } + } + ] + }).parent('.ui-dialog').overlay(); + }, + /** * to change a property(e.g. validation) of a createForm field after a createForm is rendered */ @@ -612,4 +700,4 @@ return false; } }; -})(window.jQuery, window.cloudStack); +})(window.jQuery, window.cloudStack, _l); diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index a721a44ec05..11e82b35f1c 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -70,7 +70,8 @@ action.notification : {}; var messages = action.messages; var id = args.id; - var context = args.context ? args.context : $detailView.data('view-args').context; + var context = $.extend(true, {}, + args.context ? args.context : $detailView.data('view-args').context); var _custom = $detailView.data('_custom'); var customAction = action.action.custom; var noAdd = action.noAdd; @@ -273,7 +274,7 @@ notification.desc = messages.notification(messageArgs); notification.section = 'instances'; - if (!action.createForm) { + if (!action.createForm && !action.listView) { if (messages && messages.confirm) { cloudStack.dialog.confirm({ message: messages.confirm(messageArgs), @@ -286,7 +287,7 @@ } else { performAction({ id: id }); } - } else { + } else if (action.createForm) { cloudStack.dialog.createForm({ form: action.createForm, after: function(args) { @@ -301,6 +302,15 @@ }, context: context }); + } else if (action.listView) { + cloudStack.dialog.listView({ + context: context, + listView: action.listView, + after: function(args) { + context = args.context; + performAction(); + } + }); } } }, From c6c85387fb69beec39357b7a4f217db4df8bd443 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 15:09:30 -0700 Subject: [PATCH 057/201] VPC: Use listView selector for assignVm action --- ui/css/cloudstack3.css | 6 ++++-- ui/scripts/vpc.js | 21 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 16584537905..da647877f27 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -11871,12 +11871,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it } .add .icon, -.addNew .icon { +.addNew .icon, +.assignVm .icon { background-position: -37px -61px; } .add:hover .icon, -.addNew:hover .icon { +.addNew:hover .icon, +.assignVm:hover .icon { background-position: -37px -643px; } diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 7778a2d0d6b..50fa5db708b 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -437,9 +437,24 @@ detailView: { name: 'Internal Lb details', actions: { - //assignVm: { - - //} + assignVm: { + label: 'Assign VMs to LB', + messages: { + notification: function(args) { return 'Assign VM to internal LB rule'; } + }, + listView: $.extend(true, {}, cloudStack.sections.instances.listView, { + type: 'checkbox', + filters: false + }), + action: function(args) { + args.response.success(); + }, + notification: { + poll: function(args) { + args.complete(); + } + } + } }, tabs: { details: { From b88da4e1c108912fe8162cf2fd18be08eade64b4 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 15:36:50 -0700 Subject: [PATCH 058/201] VPC UI: Reload chart on perform detailView action --- ui/modules/vpc/vpc.js | 3 +++ ui/scripts/ui/widgets/listView.js | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 3c44a4cabca..cc0273fcbb1 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -188,6 +188,9 @@ if (section.listView) { $section.listView($.extend(true, {}, section, { + onActionComplete: function() { + $dashboardItem.closest('.vpc-network-chart').trigger('reload'); + }, context: context })); } diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 031874dff1f..d68f91fac7c 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -104,6 +104,10 @@ cloudStack.ui.notifications.add( notification, function(args) { + if (listViewArgs.onActionComplete) { + listViewArgs.onActionComplete(); + } + if ($item.is(':visible') && !isHeader) { replaceItem( $item, @@ -175,6 +179,10 @@ if (additional && additional.success) additional.success(args); + if (listViewArgs.onActionComplete == true) { + listViewArgs.onActionComplete(); + } + cloudStack.ui.notifications.add( notification, @@ -213,6 +221,10 @@ if (options.complete) { options.complete(args); } + + if (listViewArgs.onActionComplete) { + listViewArgs.onActionComplete(); + } }, {}, @@ -1187,6 +1199,10 @@ $quickViewTooltip.hide(); }, onActionComplete: function() { + if (listViewArgs.onActionComplete) { + listViewArgs.onActionComplete(); + } + $tr.removeClass('loading').find('td:last .loading').remove(); $quickViewTooltip.remove(); } @@ -1798,6 +1814,8 @@ }); } + detailViewArgs.data.onActionComplete = listViewArgs.onActionComplete; + createDetailView( detailViewArgs, function($detailView) { //complete(), callback funcion From 24dd6fb66ff68c2969364340f72ea9aab5faf58e Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 15:40:00 -0700 Subject: [PATCH 059/201] Cleanup formatting --- ui/scripts/vpc.js | 208 +++++++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 105 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 50fa5db708b..450b5326ca8 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -610,99 +610,97 @@ id: { label: 'id' } }, dataProvider: function(args) { - $.ajax({ - - url:createURL('listNetworkACLLists&vpc_id=' + args.context.vpc[0].id), - success:function(json){ - var items = json.listnetworkacllistsresponse.networkacllist; - - args.response.success({ - data:items + url:createURL('listNetworkACLLists&vpc_id=' + args.context.vpc[0].id), + success:function(json){ + var items = json.listnetworkacllistsresponse.networkacllist; + + args.response.success({ + data:items }); - } - }); + } + }); }, - actions:{ - add:{ - label:'Add ACL List', - createForm:{ + actions:{ + add:{ + label:'Add ACL List', + createForm:{ label: 'Add ACL List', fields:{ name:{label:'ACL List Name',validation:{required:true}}, description:{label:'Description',validation:{required:true}} } }, - messages: { - notification: function(args) { - return 'Add Network ACL List'; - } - }, - action:function(args){ - var data = { - name:args.data.name, - description:args.data.description + messages: { + notification: function(args) { + return 'Add Network ACL List'; + } + }, + action:function(args){ + var data = { + name:args.data.name, + description:args.data.description - }; + }; - $.ajax({ - url:createURL('createNetworkACLList&vpcid='+ args.context.vpc[0].id), - data:data, - success:function(json){ - var items = json.createnetworkacllistresponse; - args.response.success({ - data:items - }); - } - }); + $.ajax({ + url:createURL('createNetworkACLList&vpcid='+ args.context.vpc[0].id), + data:data, + success:function(json){ + var items = json.createnetworkacllistresponse; + args.response.success({ + data:items + }); + } + }); } - } + } }, detailView: { isMaximized: true, - actions:{ - deleteacllist:{ - label:'Delete ACL List', - messages: { - confirm: function(args) { - return 'Are you sure you want to delete this ACL list ?'; - }, - notification: function(args) { - return 'Delete ACL list'; - } - }, - action:function(args){ - $.ajax({ - url:createURL('deleteNetworkACLList&id=' + args.context.aclLists[0].id), - success:function(json){ - var jid = json.deletenetworkacllistresponse.jobid; - args.response.success( - {_custom: - { jobId: jid - } - } - ); - - }, - error:function(json){ - args.response.error(parseXMLHttpResponse(json)); - - } - }); - }, - notification: { - poll: pollAsyncJobResult - } - + actions:{ + deleteacllist:{ + label:'Delete ACL List', + messages: { + confirm: function(args) { + return 'Are you sure you want to delete this ACL list ?'; + }, + notification: function(args) { + return 'Delete ACL list'; } }, + action:function(args){ + $.ajax({ + url:createURL('deleteNetworkACLList&id=' + args.context.aclLists[0].id), + success:function(json){ + var jid = json.deletenetworkacllistresponse.jobid; + args.response.success( + {_custom: + { jobId: jid + } + } + ); + + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); + + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + + } + }, tabs: { - details: { + details: { title: 'label.details', fields: [ @@ -714,22 +712,22 @@ ], dataProvider: function(args) { - var items = args.context.aclLists[0]; - args.response.success({ - data: items, - actionFilter: function(args) { - var allowedActions = []; - if(isAdmin()) { - allowedActions.push("deleteacllist"); + var items = args.context.aclLists[0]; + args.response.success({ + data: items, + actionFilter: function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("deleteacllist"); - } - return allowedActions; - } + } + return allowedActions; + } - }); + }); } - }, + }, aclRules: { title: 'ACL List Rules', @@ -740,32 +738,32 @@ networkid: false }, dataProvider: function(args) { - $.ajax({ - url:createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), - success:function(json){ + $.ajax({ + url:createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), + success:function(json){ var items = json.listnetworkaclsresponse.networkacl; - args.response.success({ - data:items - /* { - cidrlist: '10.1.1.0/24', - protocol: 'TCP', - startport: 22, endport: 22, - networkid: 0, - traffictype: 'Egress' - }, - { - cidrlist: '10.2.1.0/24', - protocol: 'UDP', - startport: 56, endport: 72, - networkid: 0, - trafficType: 'Ingress' - } - ]*/ + args.response.success({ + data:items + /* { + cidrlist: '10.1.1.0/24', + protocol: 'TCP', + startport: 22, endport: 22, + networkid: 0, + traffictype: 'Egress' + }, + { + cidrlist: '10.2.1.0/24', + protocol: 'UDP', + startport: 56, endport: 72, + networkid: 0, + trafficType: 'Ingress' + } + ]*/ + }); + } }); - } - }); - } + } })); } } From 62f7ab6ffe896b87be12a4048f9be88636a5bf3e Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 15:48:11 -0700 Subject: [PATCH 060/201] Delete ACL action: Rename to 'remove' to fix UI feedback --- ui/scripts/vpc.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 450b5326ca8..617d9faa0a5 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -661,7 +661,7 @@ detailView: { isMaximized: true, actions:{ - deleteacllist:{ + remove: { label:'Delete ACL List', messages: { confirm: function(args) { @@ -682,26 +682,20 @@ } } ); - }, error:function(json){ args.response.error(parseXMLHttpResponse(json)); - } }); }, notification: { poll: pollAsyncJobResult } - } }, - tabs: { - details: { - title: 'label.details', fields: [ { @@ -709,7 +703,6 @@ description: {label:'Description'}, id:{label:'id'} } - ], dataProvider: function(args) { var items = args.context.aclLists[0]; @@ -718,13 +711,11 @@ actionFilter: function(args) { var allowedActions = []; if(isAdmin()) { - allowedActions.push("deleteacllist"); + allowedActions.push("remove"); } return allowedActions; } - - }); } }, From 7c05bb13ccd3cb5be9e22ec472db4b8f368bd4f8 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 15:51:15 -0700 Subject: [PATCH 061/201] Fix quickview for ACL list --- ui/scripts/vpc.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 617d9faa0a5..e47cb1244b7 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -706,16 +706,18 @@ ], dataProvider: function(args) { var items = args.context.aclLists[0]; - args.response.success({ - data: items, - actionFilter: function(args) { - var allowedActions = []; - if(isAdmin()) { - allowedActions.push("remove"); + setTimeout(function() { + args.response.success({ + data: items, + actionFilter: function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("remove"); + } + return allowedActions; } - return allowedActions; - } + }); }); } }, From 3c2be57c35877c98d165c5f5be464815f6af2484 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 21 May 2013 15:57:58 -0700 Subject: [PATCH 062/201] CLOUDSTACK-747: internalLb in VPC - internal LB detail View - implement action assign VM to internal lb. --- ui/scripts/vpc.js | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index e47cb1244b7..23e7b0cc898 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -446,13 +446,33 @@ type: 'checkbox', filters: false }), - action: function(args) { - args.response.success(); + action: function(args) { + var vms = args.context.instances; + var array1 = []; + for(var i = 0; i < vms.length; i++) { + array1.push(vms[i].id); + } + var virtualmachineids = array1.join(','); + + $.ajax({ + url: createURL('assignToLoadBalancerRule'), + data: { + id: args.context.internalLoadBalancers[0].id, + virtualmachineids: virtualmachineids + }, + dataType: 'json', + async: true, + success: function(data) { + debugger; + var jid = data.assigntoloadbalancerruleresponse.jobid; + args.response.success({ + _custom: { jobId: jid } + }); + } + }); }, notification: { - poll: function(args) { - args.complete(); - } + poll: pollAsyncJobResult } } }, From 4ce76429e28a1e1da6ca14d79082da1f1cf0a74f Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 16:16:27 -0700 Subject: [PATCH 063/201] Add internal LB count to VPC chart --- ui/scripts/vpc.js | 161 ++++++++++++++++++++++++++++------------------ 1 file changed, 97 insertions(+), 64 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 23e7b0cc898..f96d552b49d 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3084,72 +3084,105 @@ async: true, success: function(json) { var networks = json.listnetworksresponse.network; - if(networks != null && networks.length > 0) { - for(var i = 0; i < networks.length; i++) { - $.ajax({ - url: createURL("listVirtualMachines"), - dataType: "json", - data: { - networkid: networks[i].id, - listAll: true - }, - async: false, - success: function(json) { - networks[i].virtualMachines = json.listvirtualmachinesresponse.virtualmachine; - } - }); + var loadBalancers; + var error = false; + + // Get load balancers + $.ajax({ + url: createURL('listLoadBalancers'), + data: { details: 'min', vpcid: args.context.vpc[0].id }, + success: function(json) { + loadBalancers = json.listloadbalancerssresponse.loadbalancer ? + json.listloadbalancerssresponse.loadbalancer : [] + }, + error: function(json) { + error = true; } - } - args.response.success({ - routerDashboard: [ - { - id: 'privateGateways', - name: 'Private gateways', - total: 0 - }, - { - id: 'publicIPs', - name: 'Public IP addresses', - total: 0 - }, - { - id: 'siteToSiteVPNs', - name: 'Site-to-site VPNs', - total: 0 - }, - { - id: 'networkACLLists', - name: 'Network ACL lists', - total: 0 - } - ], - tiers: $(networks).map(function(index, tier) { - return $.extend(tier, { - _dashboardItems: [ - { - id: 'tierLoadBalancers', - name: 'Load balancers', - totalMultiLine: '0 Internal
    0 Public' - }, - { - id: 'tierPortForwarders', - name: 'Port forwarders', - total: 0 - }, - { - id: 'tierStaticNATs', - name: 'Static NATs', - total: 0 - }, - { - id: 'tierVMs', - name: 'Virtual Machines', - total: $.isArray(tier.virtualMachines) ? tier.virtualMachines.length : 0 - } - ] - }); - }) }); + + var dataTimer = setInterval(function() { + console.log('timer'); + + var complete = loadBalancers; + + if (complete) { + clearInterval(dataTimer); + + if(networks != null && networks.length > 0) { + for(var i = 0; i < networks.length; i++) { + $.ajax({ + url: createURL("listVirtualMachines"), + dataType: "json", + data: { + networkid: networks[i].id, + listAll: true + }, + async: false, + success: function(json) { + networks[i].virtualMachines = json.listvirtualmachinesresponse.virtualmachine; + } + }); + } + } + args.response.success({ + routerDashboard: [ + { + id: 'privateGateways', + name: 'Private gateways', + total: 0 + }, + { + id: 'publicIPs', + name: 'Public IP addresses', + total: 0 + }, + { + id: 'siteToSiteVPNs', + name: 'Site-to-site VPNs', + total: 0 + }, + { + id: 'networkACLLists', + name: 'Network ACL lists', + total: 0 + } + ], + tiers: $(networks).map(function(index, tier) { + var internalLoadBalancers = $.grep(loadBalancers, function(lb) { + return lb.networkid == tier.id; + }); + + return $.extend(tier, { + _dashboardItems: [ + { + id: 'tierLoadBalancers', + name: 'Load balancers', + totalMultiLine: internalLoadBalancers.length + ' Internal
    0 Public' + }, + { + id: 'tierPortForwarders', + name: 'Port forwarders', + total: 0 + }, + { + id: 'tierStaticNATs', + name: 'Static NATs', + total: 0 + }, + { + id: 'tierVMs', + name: 'Virtual Machines', + total: $.isArray(tier.virtualMachines) ? tier.virtualMachines.length : 0 + } + ] + }); + }) + }); + } else if (error) { + clearInterval(dataTimer); + cloudStack.dialog.notice({ message: 'Error loading dashboard data.' }); + } + }, 500); } }); } From a3e97bbc3f677426e6649d20af7747678d0d2fcc Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 16:17:12 -0700 Subject: [PATCH 064/201] Remove console.log --- ui/scripts/vpc.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index f96d552b49d..e5ba23119ea 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3101,8 +3101,6 @@ }); var dataTimer = setInterval(function() { - console.log('timer'); - var complete = loadBalancers; if (complete) { From 531a2f713f6cf8712b2f0def45e6a95cc9128e97 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 21 May 2013 16:28:57 -0700 Subject: [PATCH 065/201] Add ACL lists count to VPC chart --- ui/scripts/vpc.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index e5ba23119ea..bf136b8de66 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3084,7 +3084,7 @@ async: true, success: function(json) { var networks = json.listnetworksresponse.network; - var loadBalancers; + var loadBalancers, networkACLLists; var error = false; // Get load balancers @@ -3100,8 +3100,21 @@ } }); + // Get network ACL lists + $.ajax({ + url: createURL('listNetworkACLLists'), + data: { details: 'min', 'vpc_id': args.context.vpc[0].id }, + success: function(json) { + networkACLLists = json.listnetworkacllistsresponse.networkacllist ? + json.listnetworkacllistsresponse.networkacllist : [] + }, + error: function(json) { + error = true; + } + }); + var dataTimer = setInterval(function() { - var complete = loadBalancers; + var complete = loadBalancers && networkACLLists; if (complete) { clearInterval(dataTimer); @@ -3142,7 +3155,7 @@ { id: 'networkACLLists', name: 'Network ACL lists', - total: 0 + total: networkACLLists.length } ], tiers: $(networks).map(function(index, tier) { From ba08af936150be06b9e843f91613d57b62122221 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Wed, 22 May 2013 10:50:15 +0530 Subject: [PATCH 066/201] ACL List - Addition in the detail view for Tier --- ui/scripts/vpc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index bf136b8de66..a3dadaace73 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -2635,6 +2635,8 @@ isEditable: true }, + aclid:{label:'ACL id'}, + domain: { label: 'label.domain' }, account: { label: 'label.account' } } From 1f420ec085b075e74a4b2bd45cb0a6e58473f918 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 22 May 2013 10:42:49 -0700 Subject: [PATCH 067/201] CLOUDSTACK-747: internalLb in VPC - Infrastructure menu - network service provider - add InternalLbVm. Clicking it will lead to a screen that can enable/disable provider and have instances tab that can start/stop LB Instance. --- ui/scripts/system.js | 385 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 383 insertions(+), 2 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 11365c1603d..32feb6dd50c 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2708,7 +2708,363 @@ } } }, - + + InternalLbVm: { + id: 'InternalLbVm', + label: 'InternalLbVm', + isMaximized: true, + type: 'detailView', + fields: { + name: { label: 'label.name' }, + ipaddress: { label: 'label.ip.address' }, + state: { label: 'label.status', indicator: { 'Enabled': 'on' } } + }, + tabs: { + network: { + title: 'label.network', + fields: [ + { + name: { label: 'label.name' } + }, + { + id: { label: 'label.id' }, + state: { label: 'label.state' }, + physicalnetworkid: { label: 'label.physical.network.ID' }, + destinationphysicalnetworkid: { label: 'label.destination.physical.network.id' }, + supportedServices: { label: 'label.supported.services' } + } + ], + dataProvider: function(args) { + refreshNspData("InternalLbVm"); + args.response.success({ + actionFilter: virtualRouterProviderActionFilter, + data: $.extend(nspMap["InternalLbVm"], { + supportedServices: nspMap["InternalLbVm"].servicelist.join(', ') + }) + }); + } + }, + + instances: { + title: 'label.instances', + listView: { + label: 'label.virtual.appliances', + id: 'internallbinstances', + fields: { + name: { label: 'label.name' }, + zonename: { label: 'label.zone' }, + routerType: { + label: 'label.type' + }, + state: { + converter: function(str) { + // For localization + return str; + }, + label: 'label.status', + indicator: { + 'Running': 'on', + 'Stopped': 'off', + 'Error': 'off' + } + } + }, + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + + var routers = []; + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + success: function(json) { + var items = json.listinternallbvmssresponse.internalloadbalancervm ? + json.listinternallbvmssresponse.internalloadbalancervm : []; + + $(items).map(function(index, item) { + routers.push(item); + }); + + // Get project routers + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"), + success: function(json) { + var items = json.listinternallbvmssresponse.internalloadbalancervm ? + json.listinternallbvmssresponse.internalloadbalancervm : []; + + $(items).map(function(index, item) { + routers.push(item); + }); + args.response.success({ + actionFilter: internallbinstanceActionfilter, + data: $(routers).map(mapRouterType) + }); + } + }); + } + }); + }, + detailView: { + name: 'Virtual applicance details', + actions: { + start: { + label: 'Start LB VM', + messages: { + confirm: function(args) { + return 'Please confirm you want to start LB VM'; + }, + notification: function(args) { + return 'Start LB VM'; + } + }, + action: function(args) { + $.ajax({ + url: createURL('startInternalLoadBalancerVM&id=' + args.context.internallbinstances[0].id), + dataType: 'json', + async: true, + success: function(json) { + var jid = json.startinternallbvmresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.internalloadbalancervm; + }, + getActionFilter: function() { + return internallbinstanceActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + stop: { + label: 'Stop LB VM', + createForm: { + title: 'Please confirm you want to stop LB VM', + desc: 'Stop LB VM', + fields: { + forced: { + label: 'force.stop', + isBoolean: true, + isChecked: false + } + } + }, + messages: { + notification: function(args) { + return 'Stop LB VM'; + } + }, + action: function(args) { + var array1 = []; + array1.push("&forced=" + (args.data.forced == "on")); + $.ajax({ + url: createURL('stopInternalLoadBalancerVM&id=' + args.context.internallbinstances[0].id + array1.join("")), + dataType: 'json', + async: true, + success: function(json) { + var jid = json.stopinternallbvmresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.internalloadbalancervm; + }, + getActionFilter: function() { + return internallbinstanceActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + preFilter: function(args) { + var hiddenFields = []; + if (!args.context.internallbinstances[0].project) { + hiddenFields.push('project'); + hiddenFields.push('projectid'); + } + if(selectedZoneObj.networktype == 'Basic') { + hiddenFields.push('publicip'); //In Basic zone, guest IP is public IP. So, publicip is not returned by listRouters API. Only guestipaddress is returned by listRouters API. + } + return hiddenFields; + }, + fields: [ + { + name: { label: 'label.name' }, + project: { label: 'label.project' } + }, + { + id: { label: 'label.id' }, + projectid: { label: 'label.project.id' }, + state: { label: 'label.state' }, + guestnetworkid: { label: 'label.network.id' }, + publicip: { label: 'label.public.ip' }, + guestipaddress: { label: 'label.guest.ip' }, + linklocalip: { label: 'label.linklocal.ip' }, + hostname: { label: 'label.host' }, + serviceofferingname: { label: 'label.compute.offering' }, + networkdomain: { label: 'label.network.domain' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' }, + created: { label: 'label.created', converter: cloudStack.converters.toLocalDate }, + isredundantrouter: { + label: 'label.redundant.router', + converter: cloudStack.converters.toBooleanText + }, + redundantRouterState: { label: 'label.redundant.state' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&id=" + args.context.internallbinstances[0].id), + dataType: 'json', + async: true, + success: function(json) { + var jsonObj = json.listinternallbvmssresponse.internalloadbalancervm[0]; + addExtraPropertiesToRouterInstanceObject(jsonObj); + args.response.success({ + actionFilter: internallbinstanceActionfilter, + data: jsonObj + }); + } + }); + } + }, + nics: { + title: 'label.nics', + multiple: true, + fields: [ + { + name: { label: 'label.name', header: true }, + type: { label: 'label.type' }, + traffictype: { label: 'label.traffic.type' }, + networkname: { label: 'label.network.name' }, + netmask: { label: 'label.netmask' }, + ipaddress: { label: 'label.ip.address' }, + id: { label: 'label.id' }, + networkid: { label: 'label.network.id' }, + isolationuri: { label: 'label.isolation.uri' }, + broadcasturi: { label: 'label.broadcast.uri' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listInternalLoadBalancerVMs&id=" + args.context.internallbinstances[0].id), + dataType: 'json', + async: true, + success: function(json) { + var jsonObj = json.listinternallbvmssresponse.internalloadbalancervm[0].nic; + + args.response.success({ + actionFilter: internallbinstanceActionfilter, + data: $.map(jsonObj, function(nic, index) { + var name = 'NIC ' + (index + 1); + if (nic.isdefault) { + name += ' (' + _l('label.default') + ')'; + } + return $.extend(nic, { + name: name + }); + }) + }); + } + }); + } + } + } + } + } + } + }, + actions: { + enable: { + label: 'label.enable.provider', + action: function(args) { + $.ajax({ + url: createURL("updateNetworkServiceProvider&id=" + nspMap["InternalLbVm"].id + "&state=Enabled"), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkserviceproviderresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + $(window).trigger('cloudStack.fullRefresh'); + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.confirm.enable.provider'; + }, + notification: function() { + return 'label.enable.provider'; + } + }, + notification: { poll: pollAsyncJobResult } + }, + disable: { + label: 'label.disable.provider', + action: function(args) { + $.ajax({ + url: createURL("updateNetworkServiceProvider&id=" + nspMap["InternalLbVm"].id + "&state=Disabled"), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkserviceproviderresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + $(window).trigger('cloudStack.fullRefresh'); + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.confirm.disable.provider'; + }, + notification: function() { + return 'label.disable.provider'; + } + }, + notification: { poll: pollAsyncJobResult } + } + } + }, + vpcVirtualRouter: { id: 'vpcVirtualRouterProviders', label: 'VPC Virtual Router', @@ -12020,7 +12376,20 @@ } return allowedActions; } + + var internallbinstanceActionfilter = function(args) { + var jsonObj = args.context.item; + var allowedActions = []; + if (jsonObj.state == 'Running') { + allowedActions.push("stop"); + } + else if (jsonObj.state == 'Stopped') { + allowedActions.push("start"); + } + return allowedActions; + } + var systemvmActionfilter = function(args) { var jsonObj = args.context.item; var allowedActions = []; @@ -12102,6 +12471,9 @@ case "VirtualRouter": nspMap["virtualRouter"] = items[i]; break; + case "InternalLbVm": + nspMap["InternalLbVm"] = items[i]; + break; case "VpcVirtualRouter": nspMap["vpcVirtualRouter"] = items[i]; break; @@ -12178,7 +12550,16 @@ state: nspMap.midoNet? nspMap.midoNet.state : 'Disabled' } ); - nspHardcodingArray.push( + + nspHardcodingArray.push( + { + id: 'InternalLbVm', + name: 'InternalLbVm', + state: nspMap.InternalLbVm ? nspMap.InternalLbVm.state : 'Disabled' + } + ); + + nspHardcodingArray.push( { id: 'vpcVirtualRouter', name: 'VPC Virtual Router', From 8acdd6f4369c334727ac44b519015cd9bd4d25e2 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 22 May 2013 11:03:56 -0700 Subject: [PATCH 068/201] CLOUDSTACK-747: internal LB in VPC - remove module internalLbProvider since internalLbVm section has been added in system.js --- .../internalLbProvider/internalLbProvider.js | 182 ------------------ ui/modules/modules.js | 3 +- 2 files changed, 1 insertion(+), 184 deletions(-) delete mode 100644 ui/modules/internalLbProvider/internalLbProvider.js diff --git a/ui/modules/internalLbProvider/internalLbProvider.js b/ui/modules/internalLbProvider/internalLbProvider.js deleted file mode 100644 index aaa386ee246..00000000000 --- a/ui/modules/internalLbProvider/internalLbProvider.js +++ /dev/null @@ -1,182 +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. -(function($, cloudStack) { - cloudStack.modules.internalLbProvider = function(module) { - var internalLbDeviceViewAll = [ - { - label: 'Devices', - path: '_zone.internalLbDevices' - } - ]; - - var internalLbListView = { - id: 'internalLbDevices', - fields: { - resourcename: { label: 'Resource Name' }, - provider: { label: 'Provider' } - }, - dataProvider: function(args) { - args.response.success({ data: [] }); - }, - actions: { - add: { - label: 'Add internal LB device', - - messages: { - notification: function(args) { - return 'Add internal LB device'; - } - }, - - createForm: { - title: 'Add internal LB device', - fields: { - hostname: { - label: 'label.host', - validation: { required: true } - }, - username: { - label: 'label.username', - validation: { required: true } - }, - password: { - label: 'label.password', - isPassword: true, - validation: { required: true } - } - } - }, - - action: function(args) { - args.response.success(); - }, - - notification: { - poll: function(args) { - args.complete(); - } - } - } - }, - - detailView: { - name: 'Internal LB resource details', - actions: { - remove: { - label: 'delete Internal LB resource', - messages: { - confirm: function(args) { - return 'Please confirm you want to delete Internal LB resource'; - }, - notification: function(args) { - return 'delete Internal LB resource'; - } - }, - action: function(args) { - args.response.success(); - }, - notification: { - poll: function(args) { - args.complete(); - } - } - } - }, - - tabs: { - details: { - title: 'label.details', - fields: [ - { - resourcename: { label: 'Resource Name' } - }, - { - resourceid: { label: 'Resource ID'}, - provider: { label: 'Provider' }, - RESOURCE_NAME: { label: 'Resource Name'} - } - ], - dataProvider: function(args) { - args.response.success({ data: args.context.internalLbDevices[0] }); - } - } - } - } - }; - - var internalLbProviderDetailView = { - id: 'internalLbProvider', - label: 'internal LB', - viewAll: internalLbDeviceViewAll, - tabs: { - details: { - title: 'label.details', - fields: [ - { - name: { label: 'label.name' } - }, - { - state: { label: 'label.state' }, - id: { label: 'label.id' }, - servicelist: { - label: 'Services', - converter: function(args){ - if(args) - return args.join(', '); - else - return ''; - } - } - } - ], - dataProvider: function(args) { - $.ajax({ - url: createURL('listNetworkServiceProviders'), - data: { - name: 'InternalLb', - physicalnetworkid: args.context.physicalNetworks[0].id - }, - success: function(json){ - var items = json.listnetworkserviceprovidersresponse.networkserviceprovider; - if(items != null && items.length > 0) { - args.response.success({ data: items[0] }); - } - else { - args.response.success({ - data: { - name: 'InternalLb', - state: 'Disabled' - } - }) - } - } - }); - } - } - } - }; - - module.infrastructure.networkServiceProvider({ - id: 'internalLb', - name: 'Internal LB', - //state: 'Disabled', //don't know state until log in and visit Infrastructure menu > zone detail > physical network > network service providers - listView: internalLbListView, - - detailView: internalLbProviderDetailView - }); - }; -}(jQuery, cloudStack)); diff --git a/ui/modules/modules.js b/ui/modules/modules.js index 1ff69ef1f15..1e4cd45c833 100644 --- a/ui/modules/modules.js +++ b/ui/modules/modules.js @@ -19,7 +19,6 @@ 'vpc', 'infrastructure', 'vnmcNetworkProvider', - 'vnmcAsa1000v', - 'internalLbProvider' + 'vnmcAsa1000v' ]; }(jQuery, cloudStack)); From b11c44f91d418d498c994f7fbf2b4791fe89dcab Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 11:11:29 -0700 Subject: [PATCH 069/201] Internal LB: Pre-select existing VMs on LB rule --- ui/scripts/vpc.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index a3dadaace73..be7fdd72cbc 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -444,7 +444,34 @@ }, listView: $.extend(true, {}, cloudStack.sections.instances.listView, { type: 'checkbox', - filters: false + filters: false, + dataProvider: function(args) { + $.ajax({ + url: createURL('listVirtualMachines'), + data: { + networkid: args.context.networks[0].id, + listAll: true + }, + success: function(json) { + var instances = json.listvirtualmachinesresponse.virtualmachine; + + // Pre-select existing instances in LB rule + $(instances).map(function(index, instance) { + instance._isSelected = $.grep( + args.context.internalLoadBalancers[0].loadbalancerinstance, + + function(lbInstance) { + return lbInstance.id == instance.id; + } + ).length ? true : false; + }); + + args.response.success({ + data: instances + }); + } + }); + } }), action: function(args) { var vms = args.context.instances; From a0e75c12cd62541f750e9ff556d7b570483dbf72 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 22 May 2013 11:18:26 -0700 Subject: [PATCH 070/201] CLOUDSTACK-747: internal LB in VPC - fix a bug that Source IP Address column was not filled after Add Internal LB action was complete. --- ui/scripts/vpc.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index be7fdd72cbc..f3347358675 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -410,8 +410,8 @@ args.response.success( {_custom: {jobId: jid, - getUpdatedItem: function(json) { - return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancer; } } } @@ -422,14 +422,7 @@ args.response.success(); }, notification: { - poll: function(args) { - args.complete({ - data: { - ipaddress: '10.0.3.2', - type: 'Internal' - } - }); - } + poll: pollAsyncJobResult } } }, From f2dd65c39771ed2ba7a1248351a8d8bd3fb4af03 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 12:01:22 -0700 Subject: [PATCH 071/201] Add dashboard counts for private gateways, ip addresses and vpns --- ui/scripts/vpc.js | 59 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index f3347358675..a9e839c8efc 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3106,16 +3106,16 @@ async: true, success: function(json) { var networks = json.listnetworksresponse.network; - var loadBalancers, networkACLLists; + var loadBalancers, networkACLLists, publicIpAddresses, privateGateways, vpnGateways; var error = false; // Get load balancers $.ajax({ url: createURL('listLoadBalancers'), - data: { details: 'min', vpcid: args.context.vpc[0].id }, + data: { vpcid: args.context.vpc[0].id }, success: function(json) { loadBalancers = json.listloadbalancerssresponse.loadbalancer ? - json.listloadbalancerssresponse.loadbalancer : [] + json.listloadbalancerssresponse.loadbalancer : []; }, error: function(json) { error = true; @@ -3125,18 +3125,57 @@ // Get network ACL lists $.ajax({ url: createURL('listNetworkACLLists'), - data: { details: 'min', 'vpc_id': args.context.vpc[0].id }, + data: { 'vpc_id': args.context.vpc[0].id }, success: function(json) { networkACLLists = json.listnetworkacllistsresponse.networkacllist ? - json.listnetworkacllistsresponse.networkacllist : [] + json.listnetworkacllistsresponse.networkacllist : []; }, error: function(json) { error = true; } - }); + }); + + // Get public IPs + $.ajax({ + url: createURL('listPublicIpAddresses'), + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + publicIpAddresses = json.listpublicipaddressesresponse.publicipaddress ? + json.listpublicipaddressesresponse.publicipaddress : []; + }, + error: function(json) { + error = true; + } + }); + + // Get private gateways + $.ajax({ + url: createURL('listPrivateGateways'), + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + privateGateways = json.listprivategatewaysresponse.privategateway ? + json.listprivategatewaysresponse.privategateway : []; + }, + error: function(json) { + error = true; + } + }); + + // Get VPN gateways + $.ajax({ + url: createURL('listVpnGateways'), + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + vpnGateways = json.listvpngatewaysresponse.vpngateway ? + json.listvpngatewaysresponse.vpngateway : []; + }, + error: function(json) { + error = true; + } + }); var dataTimer = setInterval(function() { - var complete = loadBalancers && networkACLLists; + var complete = loadBalancers && networkACLLists && publicIpAddresses && privateGateways && vpnGateways; if (complete) { clearInterval(dataTimer); @@ -3162,17 +3201,17 @@ { id: 'privateGateways', name: 'Private gateways', - total: 0 + total: privateGateways.length }, { id: 'publicIPs', name: 'Public IP addresses', - total: 0 + total: publicIpAddresses.length }, { id: 'siteToSiteVPNs', name: 'Site-to-site VPNs', - total: 0 + total: vpnGateways.length }, { id: 'networkACLLists', From 763f6fd47b8179fd173f035d55f4b6609a9d2963 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 12:15:45 -0700 Subject: [PATCH 072/201] Add dashboard counts for static NAT IPs --- ui/scripts/vpc.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index a9e839c8efc..eeb69503f71 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3239,7 +3239,9 @@ { id: 'tierStaticNATs', name: 'Static NATs', - total: 0 + total: $.grep(publicIpAddresses, function(ip) { + return ip.associatednetworkid == tier.id && ip.isstaticnat; + }).length }, { id: 'tierVMs', From 9e0733c83e2204f6ca313cfa210a7ffd008524eb Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 12:28:02 -0700 Subject: [PATCH 073/201] Add dashboard count for IPs with port forwarding --- ui/scripts/vpc.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index eeb69503f71..fe3ce13e5f1 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -3106,7 +3106,7 @@ async: true, success: function(json) { var networks = json.listnetworksresponse.network; - var loadBalancers, networkACLLists, publicIpAddresses, privateGateways, vpnGateways; + var loadBalancers, networkACLLists, publicIpAddresses, privateGateways, vpnGateways, portForwardingRules; var error = false; // Get load balancers @@ -3148,6 +3148,19 @@ } }); + // Get port forwarding rules + $.ajax({ + url: createURL('listPortForwardingRules'), + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + portForwardingRules = json.listportforwardingrulesresponse.portforwardingrule ? + json.listportforwardingrulesresponse.portforwardingrule : []; + }, + error: function(json) { + error = true; + } + }); + // Get private gateways $.ajax({ url: createURL('listPrivateGateways'), @@ -3234,7 +3247,14 @@ { id: 'tierPortForwarders', name: 'Port forwarders', - total: 0 + total: $.grep(publicIpAddresses, function(ip) { + return $.grep( + portForwardingRules, + function(pf) { + return pf.ipaddressid == ip.id; + } + ).length ? true : false; + }).length }, { id: 'tierStaticNATs', From ff58052d2cd5f2ed821bef04c18960ef0d18fac2 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 22 May 2013 13:18:24 -0700 Subject: [PATCH 074/201] CLOUDSTACK-747: internal LB in VPC - internal LB detailView - add rules tab, assignedVMs tab. --- ui/scripts/vpc.js | 49 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index fe3ce13e5f1..5c2f0266d1b 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -482,8 +482,7 @@ }, dataType: 'json', async: true, - success: function(data) { - debugger; + success: function(data) { var jid = data.assigntoloadbalancerruleresponse.jobid; args.response.success({ _custom: { jobId: jid } @@ -519,7 +518,51 @@ } }); } - } + }, + rules: { + title: 'label.rules', + multiple: true, + fields: [ + { + sourceport: { label: 'Source Port' }, + instanceport: { label: 'Instance Port' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item.loadbalancerrule }); + } + }); + } + } , + assignedVms: { + title: 'Assigned VMs', + multiple: true, + fields: [ + { + name: { label: 'label.name' }, + ipaddress: { label: 'label.ip.address' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item.loadbalancerinstance }); + } + }); + } + } } } } From 19321d4eeb7accd2bd67af1c8b2c2a5988a23ac0 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Wed, 22 May 2013 15:27:04 -0700 Subject: [PATCH 075/201] CLOUDSTACK-2629: ListRouters with networkid throws exception. --- server/src/com/cloud/api/query/QueryManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index a126925e5f0..c586a7b19f2 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -1095,7 +1095,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (networkId != null) { - sc.setJoinParameters("nicSearch", "networkId", networkId); + sc.setParameters("networkId", networkId); } if (vpcId != null) { From e6863c612bfeda957c4e2acf14647c029a48d2c8 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 22 May 2013 15:39:22 -0700 Subject: [PATCH 076/201] Integration test for advanced zone with security groups Description: This patch includes three parts for advancedsg: (1) Marvin support. (2) devcloud support. (3) integration test scripts Testing Done: devcloud testing ok. Signed-off-by: Anthony Xu --- setup/dev/advancedsg.cfg | 185 +++++ .../component/test_advancedsg_networks.py | 753 ++++++++++++++++++ .../component/test_egress_rules.py | 20 +- .../component/test_security_groups.py | 22 +- tools/devcloud/devcloud-advancedsg.cfg | 119 +++ tools/marvin/marvin/configGenerator.py | 123 +++ tools/marvin/marvin/deployDataCenter.py | 32 +- .../marvin/sandbox/advancedsg/__init__.py | 18 + .../sandbox/advancedsg/advancedsg_env.py | 150 ++++ .../sandbox/advancedsg/setup.properties | 61 ++ tools/marvin/setup.py | 2 +- 11 files changed, 1461 insertions(+), 24 deletions(-) create mode 100644 setup/dev/advancedsg.cfg create mode 100644 test/integration/component/test_advancedsg_networks.py create mode 100644 tools/devcloud/devcloud-advancedsg.cfg create mode 100644 tools/marvin/marvin/sandbox/advancedsg/__init__.py create mode 100644 tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py create mode 100644 tools/marvin/marvin/sandbox/advancedsg/setup.properties diff --git a/setup/dev/advancedsg.cfg b/setup/dev/advancedsg.cfg new file mode 100644 index 00000000000..e6922b639e5 --- /dev/null +++ b/setup/dev/advancedsg.cfg @@ -0,0 +1,185 @@ +# 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. + +{ + "zones": [ + { + "name": "Sandbox-Simulator", + "dns1": "10.147.28.6", + "physical_networks": [ + { + "name": "Sandbox-pnet", + "tags": [ + "cloud-simulator-pnet" + ], + "broadcastdomainrange": "Zone", + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "SecurityGroupProvider" + } + ], + "traffictypes": [ + { + "typ": "Guest" + }, + { + "typ": "Management", + "simulator": "cloud-simulator-mgmt" + } + ], + "isolationmethods": [ + "VLAN" + ] + } + ], + "securitygroupenabled": "true", + "ipranges": [ + { + "startip": "10.147.31.150", + "endip": "10.147.31.159", + "netmask": "255.255.255.0", + "vlan": "31", + "gateway": "10.147.31.1" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "10.147.29.159", + "name": "POD0", + "startip": "10.147.29.150", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "C0", + "hypervisor": "Simulator", + "hosts": [ + { + "username": "root", + "url": "http://simulator0", + "password": "password" + } + ], + "clustertype": "CloudManaged", + "primaryStorages": [ + { + "url": "nfs://10.147.28.6:/export/home/sandbox/primary", + "name": "PS0" + } + ] + } + ], + "gateway": "10.147.29.1" + } + ], + "internaldns1": "10.147.28.6", + "secondaryStorages": [ + { + "url": "nfs://10.147.28.6:/export/home/sandbox/sstor" + } + ] + } + ], + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "testclient.log" + }, + { + "name": "TestCase", + "file": "testcase.log" + } + ], + "globalConfig": [ + { + "name": "storage.cleanup.interval", + "value": "300" + }, + { + "name": "direct.agent.load.size", + "value": "1000" + }, + { + "name": "default.page.size", + "value": "10000" + }, + { + "name": "instance.name", + "value": "QA" + }, + { + "name": "workers", + "value": "10" + }, + { + "name": "vm.op.wait.interval", + "value": "5" + }, + { + "name": "account.cleanup.interval", + "value": "600" + }, + { + "name": "guest.domain.suffix", + "value": "sandbox.simulator" + }, + { + "name": "expunge.delay", + "value": "60" + }, + { + "name": "vm.allocation.algorithm", + "value": "random" + }, + { + "name": "expunge.interval", + "value": "60" + }, + { + "name": "expunge.workers", + "value": "3" + }, + { + "name": "secstorage.allowed.internal.sites", + "value": "10.147.28.0/24" + }, + { + "name": "check.pod.cidrs", + "value": "true" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "localhost", + "passwd": "password", + "user": "root", + "port": 8096 + } + ] +} diff --git a/test/integration/component/test_advancedsg_networks.py b/test/integration/component/test_advancedsg_networks.py new file mode 100644 index 00000000000..e24254d4b90 --- /dev/null +++ b/test/integration/component/test_advancedsg_networks.py @@ -0,0 +1,753 @@ +# 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. + +""" P1 tests for networks in advanced zone with security groups +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime +import netaddr + +class Services: + """ Test networks in advanced zone with security groups""" + + def __init__(self): + self.services = { + "domain": { + "name": "DOM", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "admin-XABU1@test.com", + "firstname": "admin-XABU1", + "lastname": "admin-XABU1", + "username": "admin-XABU1", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "shared_network_offering_sg": { + "name": 'MySharedOffering-sg', + "displaytext": 'MySharedOffering-sg', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData,SecurityGroup', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter', + "SecurityGroup": 'SecurityGroupProvider' + }, + }, + "shared_network_offering": { + "name": 'MySharedOffering', + "displaytext": 'MySharedOffering', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter' + }, + }, + "shared_network_sg": { + "name": "MyIsolatedNetwork - Test", + "displaytext": "MyIsolatedNetwork", + "networkofferingid":"1", + "vlan" :1200, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.2", + "endip" :"172.16.15.20", + "acltype" : "Domain", + "scope":"all", + }, + "shared_network": { + "name": "MySharedNetwork - Test", + "displaytext": "MySharedNetwork", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype" : "Domain", + "scope":"all", + }, + "isolated_network_offering": { + "name": 'Network offering-DA services', + "displaytext": 'Network offering-DA services', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "isolated_network": { + "name": "Isolated Network", + "displaytext": "Isolated Network", + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 90, + "timeout": 10, + "mode": 'advanced', + "securitygroupenabled": 'true' + } + +class TestNetworksInAdvancedSG(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestSharedNetworks, + cls + ).getClsTestClient().getApiClient() + + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.api_client = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.cleanup_networks = [] + self.cleanup_accounts = [] + self.cleanup_domains = [] + self.cleanup_projects = [] + self.cleanup_vms = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.api_client, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + #below components is not a part of cleanup because to mandate the order and to cleanup network + try: + for vm in self.cleanup_vms: + vm.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during virtual machines cleanup : %s" % e) + + try: + for project in self.cleanup_projects: + project.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during project cleanup : %s" % e) + + try: + for account in self.cleanup_accounts: + account.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during account cleanup : %s" % e) + + try: + for domain in self.cleanup_domains: + domain.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during domain cleanup : %s" % e) + + #Wait till all resources created are cleaned up completely and then attempt to delete Network + time.sleep(self.services["sleep"]) + + try: + for network in self.cleanup_networks: + network.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during network cleanup : %s" % e) + return + + def test_createIsolatedNetwork(self): + """ Test Isolated Network """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 4. listNetworkOfferings - name=myisolatedoffering, should list enabled offering + # 5. network creation should FAIL since isolated network is not supported in advanced zone with security groups. + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.name) + + #Create an user account + self.user_account = Account.create( + self.api_client, + self.services["account"], + admin=False, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.user_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.user_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The user account created is not enabled." + ) + + self.debug("User type account created: %s" % self.user_account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical network found: %s" % physical_network.id) + + #Create Network Offering + self.isolated_network_offering = NetworkOffering.create( + self.api_client, + self.services["isolated_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.isolated_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Isolated Network offering created: %s" % self.isolated_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.isolated_network_offering, + self.api_client, + id=self.isolated_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the isolated network offering created + try: + self.isolated_network = Network.create( + self.api_client, + self.services["isolated_network"], + networkofferingid=self.isolated_network_offering.id, + zoneid=self.zone.id, + ) + self.cleanup_networks.append(self.isolated_network) + self.fail("Create isolated network is invalid in advanced zone with security groups.") + except Exception as e: + self.debug("Network creation failed because create isolated network is invalid in advanced zone with security groups.") + + def test_createSharedNetwork_withoutSG(self): + """ Test Shared Network with used vlan 01 """ + + # Steps, + # 1. create an Admin account + # 2. create a shared NetworkOffering + # 3. enable the network offering + # 4. listPhysicalNetworks + # 5. createNetwork + # Validations, + # 1. listAccounts state=enabled returns your account + # 2. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 3. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 4. listPhysicalNetworks should return at least one active physical network + # 5. network creation should FAIL since there is no SecurityProvide in the network offering + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Domain admin account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["shared_network_offering"]["specifyVlan"] = "True" + self.services["shared_network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["shared_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["shared_network"]["acltype"] = "domain" + self.services["shared_network"]["networkofferingid"] = self.shared_network_offering.id + self.services["shared_network"]["physicalnetworkid"] = physical_network.id + + try: + self.shared_network = Network.create( + self.api_client, + self.services["shared_network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup_networks.append(self.shared_network) + self.fail("Network created without SecurityProvider , which is invalid") + except Exception as e: + self.debug("Network creation failed because there is no SecurityProvider in the network offering.") + + def test_deployVM_SharedwithSG(self): + """ Test VM deployment in shared networks with SecurityProvider """ + + # Steps, + # 0. create a user account + # 1. Create one shared Network (scope=ALL, different IP ranges) + # 2. deployVirtualMachine in the above networkid within the user account + # 3. delete the user account + # Validations, + # 1. shared network should be created successfully + # 2. VM should deploy successfully + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + liistall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.name) + + self.services["shared_network_offering_sg"]["specifyVlan"] = "True" + self.services["shared_network_offering_sg"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering_sg = NetworkOffering.create( + self.api_client, + self.services["shared_network_offering_sg"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering_sg) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering_sg.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network offering created: %s" % self.shared_network_offering_sg.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering_sg, + self.api_client, + id=self.shared_network_offering_sg.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering_sg.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + physical_network = list_physical_networks_response[0] + + #create network using the shared network offering created + self.services["shared_network_sg"]["acltype"] = "domain" + self.services["shared_network_sg"]["networkofferingid"] = self.shared_network_offering_sg.id + self.services["shared_network_sg"]["physicalnetworkid"] = physical_network.id + self.shared_network_sg = Network.create( + self.api_client, + self.services["shared_network_sg"], + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering_sg.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.shared_network_sg) + + list_networks_response = Network.list( + self.api_client, + id=self.shared_network_sg.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.shared_network_sg.id) + + self.shared_network_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.name, + domainid=self.admin_account.account.domainid, + networkids=self.shared_network_sg.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.shared_network_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + self.debug("Virtual Machine created: %s" % self.shared_network_admin_account_virtual_machine.id) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["shared_network_sg"]["startip"]), unicode(self.services["shared_network_sg"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index 872ca2c7b5d..607bac86325 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -194,7 +194,7 @@ class TestDefaultSecurityGroupEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_deployVM_InDefaultSecurityGroup(self): """Test deploy VM in default security group with no egress rules """ @@ -351,7 +351,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_authorizeIngressRule(self): """Test authorize ingress rule """ @@ -509,7 +509,7 @@ class TestDefaultGroupEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_default_group_with_egress(self): """Test default group with egress rule before VM deploy and ping, ssh """ @@ -710,7 +710,7 @@ class TestDefaultGroupEgressAfterDeploy(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_default_group_with_egress(self): """ Test default group with egress rule added after vm deploy and ping, ssh test @@ -893,7 +893,7 @@ class TestRevokeEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_revoke_egress_rule(self): """Test revoke security group egress rule """ @@ -1155,7 +1155,7 @@ class TestInvalidAccountAuthroize(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_invalid_account_authroize(self): """Test invalid account authroize """ @@ -1283,7 +1283,7 @@ class TestMultipleAccountsEgressRuleNeg(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_multiple_account_egress_rule_negative(self): """Test multiple account egress rules negative case """ @@ -1531,7 +1531,7 @@ class TestMultipleAccountsEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_multiple_account_egress_rule_positive(self): """Test multiple account egress rules positive case """ @@ -1822,7 +1822,7 @@ class TestStartStopVMWithEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_start_stop_vm_egress(self): """ Test stop start Vm with egress rules """ @@ -2034,7 +2034,7 @@ class TestInvalidParametersForEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_invalid_parameters(self): """ Test invalid parameters for egress rules """ diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 2ed27fe0c5d..3c25e25a34f 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -164,7 +164,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_deployVM_InDefaultSecurityGroup(self): """Test deploy VM in default security group """ @@ -243,7 +243,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_listSecurityGroups(self): """Test list security groups for admin account """ @@ -278,7 +278,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_03_accessInDefaultSecurityGroup(self): """Test access in default security group """ @@ -435,7 +435,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_authorizeIngressRule(self): """Test authorize ingress rule """ @@ -571,7 +571,7 @@ class TestRevokeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_revokeIngressRule(self): """Test revoke ingress rule """ @@ -868,7 +868,7 @@ class TestdeployVMWithUserData(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_deployVMWithUserData(self): """Test Deploy VM with User data""" @@ -1044,7 +1044,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_delete_security_grp_running_vm(self): """Test delete security group with running VM""" @@ -1128,7 +1128,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_delete_security_grp_withoout_running_vm(self): """Test delete security group without running VM""" @@ -1290,7 +1290,7 @@ class TestIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_authorizeIngressRule_AfterDeployVM(self): """Test delete security group with running VM""" @@ -1402,7 +1402,7 @@ class TestIngressRule(cloudstackTestCase): % (ingress_rule_2["id"], e)) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_revokeIngressRule_AfterDeployVM(self): """Test Revoke ingress rule after deploy VM""" @@ -1556,7 +1556,7 @@ class TestIngressRule(cloudstackTestCase): % (icmp_rule["ruleid"], e)) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_03_stopStartVM_verifyIngressAccess(self): """Test Start/Stop VM and Verify ingress rule""" diff --git a/tools/devcloud/devcloud-advancedsg.cfg b/tools/devcloud/devcloud-advancedsg.cfg new file mode 100644 index 00000000000..6c26b15f5da --- /dev/null +++ b/tools/devcloud/devcloud-advancedsg.cfg @@ -0,0 +1,119 @@ +# 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. +# +# This configuration is meant for running advanced networking with security groups, with management server on the laptop. +# It requires that the user run a DNS resolver within devcloud via 'apt-get install dnsmasq' + +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "testzone", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "shared", + "traffictypes": [ + { + "typ": "Management" + }, + { + "typ": "Guest" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "SecurityGroupProvider" + } + ], + "isolationmethods": [ + "VLAN" + ] + } + ], + "securitygroupenabled": "true", + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "1003", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "testpod", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "testcluster", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.10", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10/opt/storage/secondary" + } + ] + } + ], + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/var/log/testclient.log" + }, + { + "name": "TestCase", + "file": "/var/log/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ] +} diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index 4e82bbe387d..c970ada850a 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -638,6 +638,126 @@ def describe_setup_in_advanced_mode(): return zs +'''sample code to generate setup configuration file''' +def describe_setup_in_advancedsg_mode(): + zs = cloudstackConfiguration() + + for l in range(1): + z = zone() + z.dns1 = "8.8.8.8" + z.dns2 = "4.4.4.4" + z.internaldns1 = "192.168.110.254" + z.internaldns2 = "192.168.110.253" + z.name = "test"+str(l) + z.networktype = 'Advanced' + z.vlan = "100-2000" + z.securitygroupenabled = "true" + + pn = physical_network() + pn.name = "test-network" + pn.traffictypes = [traffictype("Guest"), traffictype("Management")] + + #If security groups are reqd + sgprovider = provider() + sgprovider.broadcastdomainrange = 'ZONE' + sgprovider.name = 'SecurityGroupProvider' + + pn.providers.append(sgprovider) + z.physical_networks.append(pn) + + '''create 10 pods''' + for i in range(2): + p = pod() + p.name = "test" +str(l) + str(i) + p.gateway = "192.168.%d.1"%i + p.netmask = "255.255.255.0" + p.startip = "192.168.%d.200"%i + p.endip = "192.168.%d.220"%i + + '''add 10 clusters''' + for j in range(2): + c = cluster() + c.clustername = "test"+str(l)+str(i) + str(j) + c.clustertype = "CloudManaged" + c.hypervisor = "Simulator" + + '''add 10 hosts''' + for k in range(2): + h = host() + h.username = "root" + h.password = "password" + memory = 8*1024*1024*1024 + localstorage=1*1024*1024*1024*1024 + #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&memory=%d&localstorage=%d"%(l,i,j,k,memory,localstorage) + h.url = "http://sim/%d%d%d%d"%(l,i,j,k) + c.hosts.append(h) + + '''add 2 primary storages''' + for m in range(2): + primary = primaryStorage() + primary.name = "primary"+str(l) + str(i) + str(j) + str(m) + #primary.url = "nfs://localhost/path%s/size=%d"%(str(l) + str(i) + str(j) + str(m), size) + primary.url = "nfs://localhost/path%s"%(str(l) + str(i) + str(j) + str(m)) + c.primaryStorages.append(primary) + + p.clusters.append(c) + + z.pods.append(p) + + '''add two secondary''' + for i in range(5): + secondary = secondaryStorage() + secondary.url = "nfs://localhost/path"+str(l) + str(i) + z.secondaryStorages.append(secondary) + + '''add default guest network''' + ips = iprange() + ips.vlan = "26" + ips.startip = "172.16.26.2" + ips.endip = "172.16.26.100" + ips.gateway = "172.16.26.1" + ips.netmask = "255.255.255.0" + z.ipranges.append(ips) + + + zs.zones.append(z) + + '''Add one mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = "localhost" + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = "localhost" + + zs.dbSvr = db + + '''add global configuration''' + global_settings = {'expunge.delay': '60', + 'expunge.interval': '60', + 'expunge.workers': '3', + } + for k,v in global_settings.iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + zs.globalConfig.append(cfg) + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = "TestClient" + testClientLogger.file = "/tmp/testclient.log" + + testCaseLogger = logger() + testCaseLogger.name = "TestCase" + testCaseLogger.file = "/tmp/testcase.log" + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + + return zs + def generate_setup_config(config, file=None): describe = config if file is None: @@ -666,6 +786,7 @@ if __name__ == "__main__": parser.add_option("-i", "--input", action="store", default=None , dest="inputfile", help="input file") parser.add_option("-a", "--advanced", action="store_true", default=False, dest="advanced", help="use advanced networking") + parser.add_option("-s", "--advancedsg", action="store_true", default=False, dest="advancedsg", help="use advanced networking with security groups") parser.add_option("-o", "--output", action="store", default="./datacenterCfg", dest="output", help="the path where the json config file generated, by default is ./datacenterCfg") (options, args) = parser.parse_args() @@ -674,6 +795,8 @@ if __name__ == "__main__": config = get_setup_config(options.inputfile) if options.advanced: config = describe_setup_in_advanced_mode() + elif options.advancedsg: + config = describe_setup_in_advancedsg_mode() else: config = describe_setup_in_basic_mode() diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 7059059beb1..cf5cf782676 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -300,7 +300,8 @@ class deployDataCenters(): createzone.securitygroupenabled = zone.securitygroupenabled createzone.localstorageenabled = zone.localstorageenabled createzone.networktype = zone.networktype - createzone.guestcidraddress = zone.guestcidraddress + if zone.securitygroupenabled != "true": + createzone.guestcidraddress = zone.guestcidraddress zoneresponse = self.apiClient.createZone(createzone) zoneId = zoneresponse.id @@ -334,10 +335,37 @@ class deployDataCenters(): self.createVlanIpRanges(zone.networktype, zone.ipranges, \ zoneId, forvirtualnetwork=True) - if zone.networktype == "Advanced": + if zone.networktype == "Advanced" and zone.securitygroupenabled != "true": self.createpods(zone.pods, zoneId) self.createVlanIpRanges(zone.networktype, zone.ipranges, \ zoneId) + elif zone.networktype == "Advanced" and zone.securitygroupenabled == "true": + listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd() + listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService" + if zone.networkofferingname is not None: + listnetworkoffering.name = zone.networkofferingname + + listnetworkofferingresponse = \ + self.apiClient.listNetworkOfferings(listnetworkoffering) + + networkcmd = createNetwork.createNetworkCmd() + networkcmd.displaytext = "Shared SG enabled network" + networkcmd.name = "Shared SG enabled network" + networkcmd.networkofferingid = listnetworkofferingresponse[0].id + networkcmd.zoneid = zoneId + + ipranges = zone.ipranges + if ipranges: + iprange = ipranges.pop() + networkcmd.startip = iprange.startip + networkcmd.endip = iprange.endip + networkcmd.gateway = iprange.gateway + networkcmd.netmask = iprange.netmask + networkcmd.vlan = iprange.vlan + + networkcmdresponse = self.apiClient.createNetwork(networkcmd) + networkId = networkcmdresponse.id + self.createpods(zone.pods, zoneId, networkId) self.createSecondaryStorages(zone.secondaryStorages, zoneId) diff --git a/tools/marvin/marvin/sandbox/advancedsg/__init__.py b/tools/marvin/marvin/sandbox/advancedsg/__init__.py new file mode 100644 index 00000000000..57823fcc162 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/__init__.py @@ -0,0 +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. + + diff --git a/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py new file mode 100644 index 00000000000..f9edf4d5803 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# 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. +''' +############################################################ +# Experimental state of scripts +# * Need to be reviewed +# * Only a sandbox +############################################################ +''' +import random +import marvin +from ConfigParser import SafeConfigParser +from optparse import OptionParser +from marvin.configGenerator import * + + +def getGlobalSettings(config): + for k, v in dict(config.items('globals')).iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + yield cfg + + +def describeResources(config): + zs = cloudstackConfiguration() + + z = zone() + z.dns1 = config.get('environment', 'dns') + z.internaldns1 = config.get('environment', 'dns') + z.name = 'Sandbox-%s'%(config.get('cloudstack', 'hypervisor')) + z.networktype = 'Advanced' + z.securitygroupenabled = 'true' + + sgprovider = provider() + sgprovider.broadcastdomainrange = 'ZONE' + sgprovider.name = 'SecurityGroupProvider' + + pn = physical_network() + pn.name = "Sandbox-pnet" + pn.tags = ["cloud-simulator-pnet"] + pn.traffictypes = [traffictype("Guest"), + traffictype("Management", {"simulator" : "cloud-simulator-mgmt"})] + pn.isolationmethods = ["VLAN"] + pn.providers.append(sgprovider) + + z.physical_networks.append(pn) + + p = pod() + p.name = 'POD0' + p.gateway = config.get('cloudstack', 'private.gateway') + p.startip = config.get('cloudstack', 'private.pod.startip') + p.endip = config.get('cloudstack', 'private.pod.endip') + p.netmask = config.get('cloudstack', 'private.netmask') + + v = iprange() + v.gateway = config.get('cloudstack', 'guest.gateway') + v.startip = config.get('cloudstack', 'guest.vlan.startip') + v.endip = config.get('cloudstack', 'guest.vlan.endip') + v.netmask = config.get('cloudstack', 'guest.netmask') + v.vlan = config.get('cloudstack', 'guest.vlan') + z.ipranges.append(v) + + c = cluster() + c.clustername = 'C0' + c.hypervisor = config.get('cloudstack', 'hypervisor') + c.clustertype = 'CloudManaged' + + h = host() + h.username = 'root' + h.password = config.get('cloudstack', 'host.password') + h.url = 'http://%s'%(config.get('cloudstack', 'host')) + c.hosts.append(h) + + ps = primaryStorage() + ps.name = 'PS0' + ps.url = config.get('cloudstack', 'primary.pool') + c.primaryStorages.append(ps) + + p.clusters.append(c) + z.pods.append(p) + + secondary = secondaryStorage() + secondary.url = config.get('cloudstack', 'secondary.pool') + z.secondaryStorages.append(secondary) + + '''Add zone''' + zs.zones.append(z) + + '''Add mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = config.get('environment', 'mshost') + mgt.user = config.get('environment', 'mshost.user') + mgt.passwd = config.get('environment', 'mshost.passwd') + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = config.get('environment', 'mysql.host') + db.user = config.get('environment', 'mysql.cloud.user') + db.passwd = config.get('environment', 'mysql.cloud.passwd') + zs.dbSvr = db + + '''Add some configuration''' + [zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)] + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = 'TestClient' + testClientLogger.file = 'testclient.log' + + testCaseLogger = logger() + testCaseLogger.name = 'TestCase' + testCaseLogger.file = 'testcase.log' + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + return zs + + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-i', '--input', action='store', default='setup.properties', \ + dest='input', help='file containing environment setup information') + parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', \ + dest='output', help='path where environment json will be generated') + + + (opts, args) = parser.parse_args() + + cfg_parser = SafeConfigParser() + cfg_parser.read(opts.input) + + cfg = describeResources(cfg_parser) + generate_setup_config(cfg, opts.output) diff --git a/tools/marvin/marvin/sandbox/advancedsg/setup.properties b/tools/marvin/marvin/sandbox/advancedsg/setup.properties new file mode 100644 index 00000000000..ee07ce23938 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/setup.properties @@ -0,0 +1,61 @@ +# 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. + + +[globals] +#global settings in cloudstack +expunge.delay=60 +expunge.interval=60 +storage.cleanup.interval=300 +account.cleanup.interval=600 +expunge.workers=3 +workers=10 +vm.allocation.algorithm=random +vm.op.wait.interval=5 +guest.domain.suffix=sandbox.simulator +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 +mshost.user=root +mshost.passwd=password +mysql.host=localhost +mysql.cloud.user=cloud +mysql.cloud.passwd=cloud +[cloudstack] +#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 +#guest network +guest.gateway=10.147.31.1 +guest.vlan=31 +guest.vlan.startip=10.147.31.150 +guest.vlan.endip=10.147.31.159 +guest.netmask=255.255.255.0 +#hypervisor host information +hypervisor=Simulator +host=simulator0 +host.password=password +#storage pools +primary.pool=nfs://10.147.28.6:/export/home/sandbox/primary +secondary.pool=nfs://10.147.28.6:/export/home/sandbox/sstor diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index 8dfd1b895d0..eeed3bfa8fd 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -45,7 +45,7 @@ setup(name="Marvin", url="https://builds.apache.org/job/cloudstack-marvin/", packages=["marvin", "marvin.cloudstackAPI", "marvin.integration", "marvin.integration.lib", "marvin.sandbox", - "marvin.sandbox.advanced", "marvin.sandbox.basic"], + "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic"], license="LICENSE.txt", install_requires=[ "mysql-connector-python", From ea440f2593b82344c1b2cc6437a2f7fc9ad68e9b Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 15:50:19 -0700 Subject: [PATCH 077/201] Add API calls to update ACL item order on drag-and-drop --- ui/scripts/ui/widgets/multiEdit.js | 18 +++++++++++++++++- ui/scripts/vpc.js | 24 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index 14f379fcc2b..936c20c48a0 100755 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -34,6 +34,7 @@ $item.append($('').append($(''))); $tr = $('').appendTo($item.find('tbody')); + $item.data('json-obj', multiRule); if (itemData) { $tr.data('multi-edit-data', itemData); @@ -828,7 +829,22 @@ $.fn.multiEdit = function(args) { $(' + + CLOUDSTACK-2709 + Egress rules are are not supported on shared networks. + > + CLOUDSTACK-1747 diff --git a/docs/en-US/egress-firewall-rule.xml b/docs/en-US/egress-firewall-rule.xml index ef0e25efd03..ab16517b458 100644 --- a/docs/en-US/egress-firewall-rule.xml +++ b/docs/en-US/egress-firewall-rule.xml @@ -23,13 +23,15 @@ The egress firewall rules are supported only on virtual routers. - The egress traffic originates from a private network to a public network, such as the Internet. By default, the egress traffic is blocked, so no outgoing traffic is allowed from a guest network to the Internet. However, you can control the egress traffic in an Advanced zone by creating egress firewall rules. When an egress firewall rule is applied, the traffic specific to the rule is allowed and the remaining traffic is blocked. When all the firewall rules are removed the default policy, Block, is applied. + + The egress firewall rules are not supported on shared networks. + Consider the following scenarios to apply egress firewall rules: From 565d740e5d446ed05a8761afa074605863bee193 Mon Sep 17 00:00:00 2001 From: radhikap Date: Tue, 28 May 2013 15:00:07 +0530 Subject: [PATCH 172/201] fixing build error --- docs/en-US/Release_Notes.xml | 45 +++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index ab734cdf5d1..2ae87320e40 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -36,8 +36,8 @@ under the License. will find instruction in the &PRODUCT; API Developer's Guide - If you find any errors or problems in this guide, please see . We hope you enjoy - working with &PRODUCT;! + If you find any errors or problems in this guide, please see . + We hope you enjoy working with &PRODUCT;! Version 4.1.0 @@ -4399,9 +4399,10 @@ under the License. CLOUDSTACK-2709 - Egress rules are are not supported on shared networks. - > + + Egress rules are are not supported on shared networks. + CLOUDSTACK-1747 @@ -4654,9 +4655,12 @@ under the License. components.xml to be on the safe side. - After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: - Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) - + After upgrading to 4.1, API clients are expected to send plain text passwords for + login and user creation, instead of MD5 hash. Incase, api client changes are not + acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default + authenticator (1st entry in the userAuthenticators adapter list is default) + <!-- Security adapters --> <bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> <property name="Adapters"> @@ -4668,7 +4672,8 @@ under the License. </property> </bean> - PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to + 4.1. If you are using Ubuntu, follow this procedure to upgrade your packages. If not, @@ -5134,9 +5139,12 @@ service cloudstack-agent start - After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: - Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) - + After upgrading to 4.1, API clients are expected to send plain text passwords for + login and user creation, instead of MD5 hash. Incase, api client changes are not + acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default + authenticator (1st entry in the userAuthenticators adapter list is default) + <!-- Security adapters --> <bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> <property name="Adapters"> @@ -5148,7 +5156,8 @@ service cloudstack-agent start </property> </bean> - PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to + 4.1. Start the first Management Server. Do not start any other Management Server nodes @@ -5729,9 +5738,12 @@ service cloudstack-agent start - After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: - Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) - + After upgrading to 4.1, API clients are expected to send plain text passwords for + login and user creation, instead of MD5 hash. Incase, api client changes are not + acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default + authenticator (1st entry in the userAuthenticators adapter list is default) + <!-- Security adapters --> <bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> <property name="Adapters"> @@ -5743,7 +5755,8 @@ service cloudstack-agent start </property> </bean> - PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to + 4.1. If you have made changes to your existing copy of the From 75a8c1ca8816df7c29aca6689f51c449b4b073b4 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 28 May 2013 16:20:19 +0530 Subject: [PATCH 173/201] CLOUDSTACK-2712: updateHvCapability mapped to serviceOfferingResponse response object of updateHypervisorCapabilities is set to ServiceOfferingResponse Signed-off-by: Prasanna Santhanam --- .../admin/config/UpdateHypervisorCapabilitiesCmd.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java index e2fe8a7b1ea..8728f915dcb 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java @@ -16,6 +16,8 @@ // under the License. package org.apache.cloudstack.api.command.admin.config; +import com.cloud.hypervisor.HypervisorCapabilities; +import com.cloud.user.Account; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -23,13 +25,9 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; -import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.log4j.Logger; -import com.cloud.hypervisor.HypervisorCapabilities; -import com.cloud.user.Account; - -@APICommand(name = "updateHypervisorCapabilities", description="Updates a hypervisor capabilities.", responseObject=ServiceOfferingResponse.class, since="3.0.0") +@APICommand(name = "updateHypervisorCapabilities", description="Updates a hypervisor capabilities.", responseObject=HypervisorCapabilitiesResponse.class, since="3.0.0") public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateHypervisorCapabilitiesCmd.class.getName()); private static final String s_name = "updatehypervisorcapabilitiesresponse"; From 4a563b64ee73fd280967ffb0d1efd9f2918c6573 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 28 May 2013 16:37:23 +0530 Subject: [PATCH 174/201] CLOUDSTACK-2713: StoragePoolResponse for a createTemplate createTemplate returns a templateresponse and not a storagepool response. Correcting the mapping to fix API docs. Signed-off-by: Prasanna Santhanam --- .../user/template/CreateTemplateCmd.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java index ba1f924fe02..6a482ac1ff2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java @@ -16,24 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.template; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.GuestOSResponse; -import org.apache.cloudstack.api.response.SnapshotResponse; -import org.apache.cloudstack.api.response.StoragePoolResponse; -import org.apache.cloudstack.api.response.TemplateResponse; -import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.api.response.VolumeResponse; -import org.apache.log4j.Logger; - import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -45,8 +27,24 @@ import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.UserContext; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCreateCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.GuestOSResponse; +import org.apache.cloudstack.api.response.SnapshotResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.log4j.Logger; -@APICommand(name = "createTemplate", responseObject = StoragePoolResponse.class, description = "Creates a template of a virtual machine. " + "The virtual machine must be in a STOPPED state. " +import java.util.Collection; +import java.util.List; +import java.util.Map; + +@APICommand(name = "createTemplate", responseObject = TemplateResponse.class, description = "Creates a template of a virtual machine. " + "The virtual machine must be in a STOPPED state. " + "A template created from this command is automatically designated as a private template visible to the account that created it.") public class CreateTemplateCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateTemplateCmd.class.getName()); From cfd8056c142c2ed49252c989b00b00cdbe7850de Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Tue, 28 May 2013 20:54:01 +0900 Subject: [PATCH 175/201] remove a call path that cause NullPointerException QemuImg.convert expects the arguments not null. --- .../kvm/storage/LibvirtStorageAdaptor.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index fa2f6707923..89e22c8d05e 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -911,20 +911,20 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath); } else { destFile = new QemuImgFile(destPath, destFormat); + try { + qemu.convert(srcFile, destFile); + } catch (QemuImgException e) { + s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + + destFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; + } } } catch (QemuImgException e) { s_logger.error("Failed to fetch the information of file " + srcFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; } } - - try { - qemu.convert(srcFile, destFile); - } catch (QemuImgException e) { - s_logger.error("Failed to convert " + srcFile.getFileName() + " to " - + destFile.getFileName() + " the error was: " + e.getMessage()); - } - } else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD)) { /** * Qemu doesn't support writing to RBD format 2 directly, so we have to write to a temporary RAW file first From b0a9adeffee823eca0bf39427ddee71bd4a5fe24 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Tue, 28 May 2013 10:51:12 -0700 Subject: [PATCH 176/201] Advance SG enabled zone. Moved following db upgrade change from 40-41 to 41-42 db upgrade path: Adnvace Zone with SG enabled: DB upgrade for Advance SG enabled zone - setup name/displayText for Guest Shared SG enabled network (it used to be system network, and name was never set for it in 2.2.x) --- setup/db/db/schema-40to410.sql | 4 ---- setup/db/db/schema-410to420.sql | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index b4c30aebe88..b7b1c7a91dd 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -1639,7 +1639,3 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Usage', 'DEFAULT', 'manageme INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (163, UUID(), 10, 'Ubuntu 12.04 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (164, UUID(), 10, 'Ubuntu 12.04 (64-bit)'); - -#update shared sg enabled network with not null name in Advance Security Group enabled network -UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain'; - diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 334aae76f33..f25588add1d 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1605,3 +1605,8 @@ CREATE TABLE `cloud`.`nic_ip_alias` ( alter table `cloud`.`vpc_gateways` add column network_acl_id bigint unsigned default 1 NOT NULL; update `cloud`.`vpc_gateways` set network_acl_id = 2; + + +#update shared sg enabled network with not null name in Advance Security Group enabled network +UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain'; + From 7ee71dfd87e0405bf41adb18c20c5825dffc8f71 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 28 May 2013 11:50:39 -0700 Subject: [PATCH 177/201] CLOUDSTACK-1974: Dedicate Guest VLAN Range - UI - Infrastructure menu - physical network - Guest - Dedicated Guest VLAN Range tab - Dedicate VLAN Range dialog - change VLAN Range field from textbox to dropdown that lists all existing Guest VLAN Ranges under the physical network. --- ui/scripts/system.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 9ac3b3083db..8b9a81fe7c7 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2153,7 +2153,20 @@ createForm: { title: 'Dedicate VLAN Range', fields: { - vlanrange: { label: 'VLAN Range(s)', validation: { required: true } }, + vlanrange: { + label: 'VLAN Range', + select: function(args) { + var items = []; + if(args.context.physicalNetworks[0].vlan != null && args.context.physicalNetworks[0].vlan.length > 0) { + var vlanranges = args.context.physicalNetworks[0].vlan.split(";"); + for(var i = 0; i < vlanranges.length ; i++) { + items.push({id: vlanranges[i], description: vlanranges[i]}); + } + } + args.response.success({data: items}); + }, + validation: { required: true } + }, account: { label: 'label.account', validation: { required: true } }, domainid: { label: 'label.domain', From 78e50c3bc8f250f0ba72207e08aaeb553eafb4b0 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 28 May 2013 14:17:47 -0700 Subject: [PATCH 178/201] CLOUDSTACK-2678: portable IP ranges - regions detailView - Portable IP Ranges - implement Add Portable IP Range action. --- ui/scripts/regions.js | 84 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index e86fd283aad..5ca416781ae 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -463,9 +463,11 @@ id: 'portableIpRanges', label: 'Portable IP Ranges', fields: { - name: { label: 'label.name' }, - gslbdomainname: { label: 'GSLB Domain Name' }, - gslblbmethod: { label: 'Algorithm' } + startip: { label: 'label.start.IP' }, + endip: { label: 'label.end.IP' }, + gateway: { label: 'label.gateway' }, + netmask: { label: 'label.netmask' }, + vlan: { label: 'label.vlan' } }, dataProvider: function(args) { $.ajax({ @@ -474,7 +476,7 @@ regionid: args.context.regions[0].id }, success: function(json) { - var items = json.listportableipresponse.portableip; + var items = json.listportableipresponse.portableiprange; args.response.success({ data: items }); @@ -483,7 +485,79 @@ args.response.error(parseXMLHttpResponse(json)); } }); - } + }, + actions: { + add: { + label: 'Add Portable IP Range', + + messages: { + notification: function(args) { + return 'Add Portable IP Range'; + } + }, + + createForm: { + title: 'Add Portable IP Range', + fields: { + startip: { + label: 'label.start.IP', + validation: { required: true } + }, + endip: { + label: 'label.end.IP', + validation: { required: true } + }, + gateway: { + label: 'label.gateway', + validation: { required: true } + }, + netmask: { + label: 'label.netmask', + validation: { required: true } + }, + vlan: { + label: 'label.vlan', + validation: { required: false } + } + } + }, + action: function(args) { + var data = { + regionid: args.context.regions[0].id, + startip: args.data.startip, + endip: args.data.endip, + gateway: args.data.gateway, + netmask: args.data.netmask + }; + if(args.data.vlan != null && args.data.vlan.length > 0) { + $.extend(data, { + vlan: args.data.vlan + }) + } + $.ajax({ + url: createURL('createPortableIpRange'), + data: data, + success: function(json) { + var jid = json.createportableiprangeresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.portableiprange; + } + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + } } }, From ecc30ddc0dfcd8237c7e9822160b3be207017520 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 28 May 2013 15:18:36 -0700 Subject: [PATCH 179/201] CLOUDSTACK-2678: portable IP ranges - regions menu - Portable IP Ranges - implement Delete Portable IP Range action. --- ui/scripts/regions.js | 94 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index 5ca416781ae..b9b6daeac20 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -489,13 +489,11 @@ actions: { add: { label: 'Add Portable IP Range', - messages: { notification: function(args) { return 'Add Portable IP Range'; } }, - createForm: { title: 'Add Portable IP Range', fields: { @@ -557,7 +555,97 @@ poll: pollAsyncJobResult } } - } + }, + + detailView: { + name: 'Portable IP Range details', + actions: { + remove: { + label: 'Delete Portable IP Range', + messages: { + confirm: function(args) { + return 'Please confirm you want to delete Portable IP Range'; + }, + notification: function(args) { + return 'Delete Portable IP Range'; + } + }, + action: function(args) { + var data = { + id: args.context.portableIpRanges[0].id + }; + $.ajax({ + url: createURL('deletePortableIpRange'), + data: data, + async: true, + success: function(json) { + var jid = json.deleteportablepublicipresponse.jobid; + args.response.success({ + _custom: { + jobId: jid + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + id: { label: 'label.id' } + }, + { + startip: { label: 'label.start.IP' }, + endip: { label: 'label.end.IP' }, + gateway: { label: 'label.gateway' }, + netmask: { label: 'label.netmask' }, + vlan: { label: 'label.vlan' }, + portableipaddress: { + label: 'Portable IPs', + converter: function(args) { + var text1 = ''; + if(args != null) { + for(var i = 0; i < args.length; i++) { + if(i > 0) { + text1 += ', '; + } + text1 += args[i].ipaddress; + } + } + return text1; + } + } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listPortableIpRanges'), + data: { + id: args.context.portableIpRanges[0].id + }, + success: function(json) { + var item = json.listportableipresponse.portableiprange[0]; + args.response.success({ + data: item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + } + } } }, From f2c468d00c2afcd2ccccc50d7f02de2c61b11997 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Tue, 28 May 2013 15:29:27 -0700 Subject: [PATCH 180/201] Removed unused imports and obsolete methods from ConfigurationManager/ConfigurationServer, NetworkManager/NetworkService --- .../ConfigurationManagerImpl.java | 130 +------- .../src/com/cloud/network/NetworkManager.java | 20 +- .../com/cloud/network/NetworkManagerImpl.java | 308 +++++++++++------- .../com/cloud/network/NetworkServiceImpl.java | 10 +- .../cloud/server/ConfigurationServerImpl.java | 29 +- .../cloud/network/MockNetworkManagerImpl.java | 22 -- .../com/cloud/vpc/MockNetworkManagerImpl.java | 54 +-- 7 files changed, 242 insertions(+), 331 deletions(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 8baf1fb134b..79375f9a86e 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -39,11 +39,6 @@ import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; -import com.cloud.dc.*; -import com.cloud.dc.dao.*; -import com.cloud.user.*; -import com.cloud.event.UsageEventUtils; -import com.cloud.utils.db.*; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.ApiConstants.LDAPParams; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; @@ -71,7 +66,13 @@ import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; -import org.apache.cloudstack.region.*; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpDao; +import org.apache.cloudstack.region.PortableIpRange; +import org.apache.cloudstack.region.PortableIpRangeDao; +import org.apache.cloudstack.region.PortableIpRangeVO; +import org.apache.cloudstack.region.PortableIpVO; +import org.apache.cloudstack.region.Region; import org.apache.cloudstack.region.dao.RegionDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; @@ -149,8 +150,8 @@ import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; import com.cloud.network.dao.PhysicalNetworkVO; -import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.element.DhcpServiceProvider; +import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; @@ -192,6 +193,11 @@ import com.cloud.utils.NumbersUtil; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicIpAlias; @@ -200,59 +206,8 @@ import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicIpAliasDao; import com.cloud.vm.dao.NicIpAliasVO; import com.cloud.vm.dao.NicSecondaryIpDao; -import edu.emory.mathcs.backport.java.util.Arrays; -import org.apache.cloudstack.acl.SecurityChecker; -import org.apache.cloudstack.api.ApiConstants.LDAPParams; -import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; -import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; -import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; -import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd; -import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd; -import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd; -import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; -import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; -import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; -import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd; -import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; -import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; -import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; -import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; -import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; -import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; -import java.net.URI; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import edu.emory.mathcs.backport.java.util.Arrays; @Component @Local(value = { ConfigurationManager.class, ConfigurationService.class }) @@ -938,10 +893,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati */ } - Grouping.AllocationState allocationState = null; if (allocationStateStr != null && !allocationStateStr.isEmpty()) { try { - allocationState = Grouping.AllocationState.valueOf(allocationStateStr); + Grouping.AllocationState.valueOf(allocationStateStr); } catch (IllegalArgumentException ex) { throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + "' to a supported state"); } @@ -1363,10 +1317,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS2"); } - Grouping.AllocationState allocationState = null; if (allocationStateStr != null && !allocationStateStr.isEmpty()) { try { - allocationState = Grouping.AllocationState.valueOf(allocationStateStr); + Grouping.AllocationState.valueOf(allocationStateStr); } catch (IllegalArgumentException ex) { throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + "' to a supported state"); } @@ -2346,7 +2299,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String endIP = cmd.getEndIp(); String newVlanGateway = cmd.getGateway(); String newVlanNetmask = cmd.getNetmask(); - Long userId = UserContext.current().getCallerUserId(); String vlanId = cmd.getVlan(); Boolean forVirtualNetwork = cmd.isForVirtualNetwork(); Long networkId = cmd.getNetworkID(); @@ -3351,43 +3303,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as your IP range's gateway, as per the IP range's netmask."); } } - - private void checkPrivateIpRangeErrors(Long podId, String startIP, String endIP) { - HostPodVO pod = _podDao.findById(podId); - if (pod == null) { - throw new InvalidParameterValueException("Please specify a valid pod."); - } - - // Check that the start and end IPs are valid - if (!NetUtils.isValidIp(startIP)) { - throw new InvalidParameterValueException("Please specify a valid start IP"); - } - - if (endIP != null && !NetUtils.isValidIp(endIP)) { - throw new InvalidParameterValueException("Please specify a valid end IP"); - } - - if (endIP != null && !NetUtils.validIpRange(startIP, endIP)) { - throw new InvalidParameterValueException("Please specify a valid IP range."); - } - - // Check that the IPs that are being added are compatible with the pod's - // CIDR - String cidrAddress = getCidrAddress(podId); - long cidrSize = getCidrSize(podId); - - if (endIP != null && !NetUtils.sameSubnetCIDR(startIP, endIP, cidrSize)) { - throw new InvalidParameterValueException("Please ensure that your start IP and end IP are in the same subnet, as per the pod's CIDR size."); - } - - if (!NetUtils.sameSubnetCIDR(startIP, cidrAddress, cidrSize)) { - throw new InvalidParameterValueException("Please ensure that your start IP is in the same subnet as the pod's CIDR address."); - } - - if (endIP != null && !NetUtils.sameSubnetCIDR(endIP, cidrAddress, cidrSize)) { - throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as the pod's CIDR address."); - } - } + private String getCidrAddress(String cidr) { String[] cidrPair = cidr.split("\\/"); @@ -3399,15 +3315,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return Integer.parseInt(cidrPair[1]); } - private String getCidrAddress(long podId) { - HostPodVO pod = _podDao.findById(podId); - return pod.getCidrAddress(); - } - - private long getCidrSize(long podId) { - HostPodVO pod = _podDao.findById(podId); - return pod.getCidrSize(); - } @Override public void checkPodCidrSubnets(long dcId, Long podIdToBeSkipped, String cidr) { @@ -4359,7 +4266,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati public boolean isOfferingForVpc(NetworkOffering offering) { boolean vpcProvider = _ntwkOffServiceMapDao.isProviderForNetworkOffering(offering.getId(), Provider.VPCVirtualRouter); - boolean internalLb = offering.getInternalLb(); return vpcProvider; } @@ -4516,6 +4422,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Note: This method will be used for entity name validations in the coming // releases (place holder for now) + @SuppressWarnings("unused") private void validateEntityName(String str) { String forbidden = "~!@#$%^&*()+="; char[] searchChars = forbidden.toCharArray(); @@ -4741,7 +4648,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String endIP = cmd.getEndIp(); String gateway = cmd.getGateway(); String netmask = cmd.getNetmask(); - Long userId = UserContext.current().getCallerUserId(); String vlanId = cmd.getVlan(); Region region = _regionDao.findById(regionId); diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 19f396abe6e..8627251e717 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -19,7 +19,6 @@ package com.cloud.network; import java.util.List; import java.util.Map; -import com.cloud.network.element.DhcpServiceProvider; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import com.cloud.dc.DataCenter; @@ -39,6 +38,7 @@ import com.cloud.network.Network.Service; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkVO; +import com.cloud.network.element.DhcpServiceProvider; import com.cloud.network.element.LoadBalancingServiceProvider; import com.cloud.network.element.StaticNatServiceProvider; import com.cloud.network.element.UserDataServiceProvider; @@ -59,7 +59,6 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; -import org.apache.cloudstack.region.PortableIp; /** * NetworkManager manages the network for the different end users. @@ -319,9 +318,6 @@ public interface NetworkManager { InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; - PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) throws InsufficientAddressCapacityException, ConcurrentOperationException; - - /** * @param addr */ @@ -346,10 +342,7 @@ public interface NetworkManager { * @return */ int getNetworkLockTimeout(); - - - boolean cleanupIpResources(long addrId, long userId, Account caller); - + boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; @@ -370,26 +363,23 @@ public interface NetworkManager { Map finalizeServicesAndProvidersForNetwork(NetworkOffering offering, Long physicalNetworkId); - List getProvidersForServiceInNetwork(Network network, Service service); StaticNatServiceProvider getStaticNatProviderForNetwork(Network network); + boolean isNetworkInlineMode(Network network); int getRuleCountForIp(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state); LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network, Scheme lbScheme); - boolean isSecondaryIpSetForNic(long nicId); - public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp) - throws InsufficientAddressCapacityException; - + public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp) throws InsufficientAddressCapacityException; List listVmNics(Long vmId, Long nicId); + String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod, Account caller, String requestedIp) throws InsufficientAddressCapacityException; - boolean removeVmSecondaryIpsOfNic(long nicId); NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index b443dca6abc..fda0773147c 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -16,9 +16,46 @@ // under the License. package com.cloud.network; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpDao; +import org.apache.cloudstack.region.PortableIpVO; +import org.apache.cloudstack.region.Region; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; -import com.cloud.agent.api.*; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckNetworkAnswer; +import com.cloud.agent.api.CheckNetworkCommand; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; @@ -26,9 +63,16 @@ import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.*; +import com.cloud.dc.AccountVlanMapVO; +import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DataCenterVnetVO; +import com.cloud.dc.Pod; +import com.cloud.dc.PodVlanMapVO; +import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.AccountVlanMapDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterVnetDao; @@ -43,25 +87,61 @@ import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.UsageEventDao; -import com.cloud.exception.*; +import com.cloud.exception.AccountLimitException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.ConnectionException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapcityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.UnsupportedServiceException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; -import com.cloud.server.ConfigurationServer; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress.State; -import com.cloud.network.Network.*; +import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Event; +import com.cloud.network.Network.GuestType; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; import com.cloud.network.Networks.AddressFormat; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; -import com.cloud.network.dao.*; -import com.cloud.network.element.*; +import com.cloud.network.dao.AccountGuestVlanMapDao; +import com.cloud.network.dao.AccountGuestVlanMapVO; +import com.cloud.network.dao.FirewallRulesDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDomainDao; +import com.cloud.network.dao.NetworkServiceMapDao; +import com.cloud.network.dao.NetworkServiceMapVO; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.dao.UserIpv6AddressDao; +import com.cloud.network.element.DhcpServiceProvider; +import com.cloud.network.element.IpDeployer; +import com.cloud.network.element.IpDeployingRequester; +import com.cloud.network.element.LoadBalancingServiceProvider; +import com.cloud.network.element.NetworkElement; +import com.cloud.network.element.StaticNatServiceProvider; +import com.cloud.network.element.UserDataServiceProvider; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.lb.LoadBalancingRulesManager; -import com.cloud.network.rules.*; +import com.cloud.network.rules.FirewallManager; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.LoadBalancerContainer.Scheme; @@ -83,7 +163,13 @@ import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingDetailsDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.org.Grouping; -import com.cloud.user.*; +import com.cloud.server.ConfigurationServer; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.User; +import com.cloud.user.UserContext; +import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.utils.Journal; @@ -92,35 +178,35 @@ import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; -import com.cloud.utils.db.*; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.JoinBuilder.JoinType; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; -import com.cloud.vm.*; +import com.cloud.vm.Nic; import com.cloud.vm.Nic.ReservationStrategy; +import com.cloud.vm.NicProfile; +import com.cloud.vm.NicVO; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.ReservationContextImpl; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; -import com.cloud.vm.dao.*; -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.region.PortableIp; -import org.apache.cloudstack.region.PortableIpDao; -import org.apache.cloudstack.region.PortableIpVO; -import org.apache.cloudstack.region.Region; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.net.URI; -import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.NicSecondaryIpDao; +import com.cloud.vm.dao.NicSecondaryIpVO; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; /** * NetworkManagerImpl implements NetworkManager. @@ -260,9 +346,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L PortableIpDao _portableIpDao; protected StateMachine2 _stateMachine; - private final HashMap _systemNetworks = new HashMap(5); - private static Long _privateOfferingId = null; - ScheduledExecutorService _executor; SearchBuilder AssignIpAddressSearch; @@ -488,11 +571,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return ipToReturn; } - @Override - public PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) throws InsufficientAddressCapacityException, ConcurrentOperationException { - return assignDedicateIpAddress(owner, null, vpcId, dcId, false); - } - @DB @Override @@ -512,6 +590,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // this ownerId comes from owner or type Account. See the class "AccountVO" and the annotations in that class // to get the table name and field name that is queried to fill this ownerid. ConcurrentOperationException ex = new ConcurrentOperationException("Unable to lock account"); + throw ex; } if (s_logger.isDebugEnabled()) { s_logger.debug("lock account " + ownerId + " is acquired"); @@ -2173,11 +2252,13 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } } + @Override public void removeNic(VirtualMachineProfile vm, Nic nic) { removeNic(vm, _nicDao.findById(nic.getId())); } + protected void removeNic(VirtualMachineProfile vm, NicVO nic) { nic.setState(Nic.State.Deallocating); _nicDao.update(nic.getId(), nic); @@ -3239,8 +3320,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return false; } - @Override - public boolean cleanupIpResources(long ipId, long userId, Account caller) { + + protected boolean cleanupIpResources(long ipId, long userId, Account caller) { boolean success = true; // Revoke all firewall rules for the ip @@ -3348,9 +3429,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L throws InsufficientAddressCapacityException { String ipaddr = null; Account caller = UserContext.current().getCaller(); - long callerUserId = UserContext.current().getCallerUserId(); // check permissions - DataCenter zone = _configMgr.getZone(zoneId); Network network = _networksDao.findById(networkId); _accountMgr.checkAccess(caller, null, false, network); @@ -3955,7 +4034,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L String requestedIpv4, String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { //This method allocates direct ip for the Shared network in Advance zones - boolean ipv4 = false, ipv6 = false; + boolean ipv4 = false; Transaction txn = Transaction.currentTxn(); txn.start(); @@ -3998,7 +4077,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L //FIXME - get ipv6 address from the placeholder if it's stored there if (network.getIp6Gateway() != null) { if (nic.getIp6Address() == null) { - ipv6 = true; UserIpv6Address ip = _ipv6Mgr.assignDirectIp6Address(dc.getId(), vm.getOwner(), network.getId(), requestedIpv6); Vlan vlan = _vlanDao.findById(ip.getVlanId()); nic.setIp6Address(ip.getAddress().toString()); @@ -4057,37 +4135,39 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - - VirtualMachine vm = vmProfile.getVirtualMachine(); - DataCenter dc = _configMgr.getZone(network.getDataCenterId()); - Host host = _hostDao.findById(vm.getHostId()); - DeployDestination dest = new DeployDestination(dc, null, null, host); - - NicProfile nic = getNicProfileForVm(network, requested, vm); - - //1) allocate nic (if needed) Always allocate if it is a user vm - if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) { - int deviceId = _nicDao.countNics(vm.getId()); - - nic = allocateNic(requested, network, false, - deviceId, vmProfile).first(); - - if (nic == null) { - throw new CloudRuntimeException("Failed to allocate nic for vm " + vm + " in network " + network); - } - - s_logger.debug("Nic is allocated successfully for vm " + vm + " in network " + network); - } - - //2) prepare nic - if (prepare) { - Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); - nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second()); - s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network); - } - - return nic; + + VirtualMachine vm = vmProfile.getVirtualMachine(); + DataCenter dc = _configMgr.getZone(network.getDataCenterId()); + Host host = _hostDao.findById(vm.getHostId()); + DeployDestination dest = new DeployDestination(dc, null, null, host); + + NicProfile nic = getNicProfileForVm(network, requested, vm); + + //1) allocate nic (if needed) Always allocate if it is a user vm + if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) { + int deviceId = _nicDao.countNics(vm.getId()); + + nic = allocateNic(requested, network, false, + deviceId, vmProfile).first(); + + if (nic == null) { + throw new CloudRuntimeException("Failed to allocate nic for vm " + vm + " in network " + network); } + + s_logger.debug("Nic is allocated successfully for vm " + vm + " in network " + network); + } + + //2) prepare nic + if (prepare) { + Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); + nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second()); + s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network); + } + + return nic; + } + + @Override public List getNicProfiles(VirtualMachine vm) { List nics = _nicDao.listByVmId(vm.getId()); @@ -4137,6 +4217,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return map; } + @Override public List getProvidersForServiceInNetwork(Network network, Service service) { Map> service2ProviderMap = getServiceProvidersMap(network.getId()); @@ -4147,6 +4228,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return null; } + protected List getElementForServiceInNetwork(Network network, Service service) { List elements = new ArrayList(); List providers = getProvidersForServiceInNetwork(network, service); @@ -4168,7 +4250,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } return elements; } - + + @Override public StaticNatServiceProvider getStaticNatProviderForNetwork(Network network) { //only one provider per Static nat service is supoprted @@ -4177,6 +4260,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return (StaticNatServiceProvider)element; } + @Override public LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network, Scheme lbScheme) { List lbElements = getElementForServiceInNetwork(network, Service.Lb); @@ -4202,7 +4286,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L assert lbElement instanceof LoadBalancingServiceProvider; return (LoadBalancingServiceProvider)lbElement; } - + + @Override public boolean isNetworkInlineMode(Network network) { NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId()); @@ -4218,47 +4303,50 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return rules.size(); } - @Override + + @Override public boolean isSecondaryIpSetForNic(long nicId) { NicVO nic = _nicDao.findById(nicId); return nic.getSecondaryIp(); } - @Override - public boolean removeVmSecondaryIpsOfNic(long nicId) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - List ipList = _nicSecondaryIpDao.listByNicId(nicId); - if (ipList != null) { - for (NicSecondaryIpVO ip: ipList) { - _nicSecondaryIpDao.remove(ip.getId()); - } - s_logger.debug("Revoving nic secondary ip entry ..."); - } - txn.commit(); - return true; - } - @Override - public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod,Account owner, - String requestedIp) throws InsufficientAddressCapacityException { - PublicIp ip = assignPublicIpAddress(dc.getId(), null, owner, VlanType.DirectAttached, networkId, requestedIp, false); - if (ip == null) { - s_logger.debug("There is no free public ip address"); - return null; - } - Ip ipAddr = ip.getAddress(); - return ipAddr.addr(); - } - - @Override - public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { - NicVO nic = new NicVO(null, null, network.getId(), null); - nic.setIp4Address(ip4Address); - nic.setReservationStrategy(ReservationStrategy.PlaceHolder); - nic.setState(Nic.State.Reserved); - nic.setVmType(vmType); - return _nicDao.persist(nic); + private boolean removeVmSecondaryIpsOfNic(long nicId) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + List ipList = _nicSecondaryIpDao.listByNicId(nicId); + if (ipList != null) { + for (NicSecondaryIpVO ip: ipList) { + _nicSecondaryIpDao.remove(ip.getId()); + } + s_logger.debug("Revoving nic secondary ip entry ..."); + } + txn.commit(); + return true; + } + + + @Override + public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod,Account owner, + String requestedIp) throws InsufficientAddressCapacityException { + PublicIp ip = assignPublicIpAddress(dc.getId(), null, owner, VlanType.DirectAttached, networkId, requestedIp, false); + if (ip == null) { + s_logger.debug("There is no free public ip address"); + return null; } + Ip ipAddr = ip.getAddress(); + return ipAddr.addr(); + } + + + @Override + public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { + NicVO nic = new NicVO(null, null, network.getId(), null); + nic.setIp4Address(ip4Address); + nic.setReservationStrategy(ReservationStrategy.PlaceHolder); + nic.setState(Nic.State.Reserved); + nic.setVmType(vmType); + return _nicDao.persist(nic); + } } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index f880bccb046..4eed735f255 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -2549,7 +2549,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (removeVlan != null){ List tokens = processVlanRange(network,removeVlan); boolean result = removeVlanRange(network, tokens.get(0), tokens.get(1)); - } if (tags != null && tags.size() > 1) { @@ -2795,9 +2794,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { return true; } - private boolean physicalNetworkHasAllocatedVnets(long zoneId, long physicalNetworkId) { - return !_dcDao.listAllocatedVnets(physicalNetworkId).isEmpty(); - } @Override @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_DELETE, eventDescription = "deleting physical network", async = true) @@ -3758,14 +3754,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } } - - + private boolean getAllowSubdomainAccessGlobal() { return _allowSubdomainNetworkAccess; } - - + @Override public List> listTrafficTypeImplementor(ListTrafficTypeImplementorsCmd cmd) { String type = cmd.getTrafficType(); diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index bc52e9a881c..35f977b5921 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -36,18 +36,12 @@ import java.util.Map; import java.util.Properties; import java.util.UUID; import java.util.regex.Pattern; -import java.util.StringTokenizer; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.configuration.*; -import com.cloud.dc.*; -import com.cloud.dc.dao.DcDetailsDao; -import com.cloud.user.*; -import com.cloud.utils.db.GenericDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; @@ -56,13 +50,25 @@ import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.configuration.Config; +import com.cloud.configuration.ConfigurationVO; +import com.cloud.configuration.Resource; import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.Resource.ResourceType; +import com.cloud.configuration.ResourceCountVO; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceCountDao; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterDetailsVO; +import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DcDetailVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.DcDetailsDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.domain.DomainVO; @@ -95,6 +101,11 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.test.IPRangeConfig; +import com.cloud.user.Account; +import com.cloud.user.AccountDetailVO; +import com.cloud.user.AccountDetailsDao; +import com.cloud.user.AccountVO; +import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.utils.PasswordGenerator; import com.cloud.utils.PropertiesUtil; @@ -106,7 +117,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.Script; -import com.cloud.uuididentity.dao.IdentityDao; @Component @@ -124,12 +134,10 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @Inject private DataCenterDao _dataCenterDao; @Inject private NetworkDao _networkDao; @Inject private VlanDao _vlanDao; - private String _domainSuffix; @Inject private DomainDao _domainDao; @Inject private AccountDao _accountDao; @Inject private ResourceCountDao _resourceCountDao; @Inject private NetworkOfferingServiceMapDao _ntwkOfferingServiceMapDao; - @Inject private IdentityDao _identityDao; @Inject private DcDetailsDao _dcDetailsDao; @Inject private ClusterDetailsDao _clusterDetailsDao; @Inject private StoragePoolDetailsDao _storagePoolDetailsDao; @@ -162,9 +170,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio // Get init String init = _configDao.getValue("init"); - // Get domain suffix - needed for network creation - _domainSuffix = _configDao.getValue("guest.domain.suffix"); - if (init == null || init.equals("false")) { s_logger.debug("ConfigurationServer is saving default values to the database."); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 53c0fa82672..7ab322b3871 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -518,14 +518,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return false; } - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#cleanupIpResources(long, long, com.cloud.user.Account) - */ - @Override - public boolean cleanupIpResources(long addrId, long userId, Account caller) { - // TODO Auto-generated method stub - return false; - } /* (non-Javadoc) * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) @@ -795,15 +787,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignVpnGatewayIpAddress(long, com.cloud.user.Account, long) - */ - @Override - public PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) - throws InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } /* (non-Javadoc) * @see com.cloud.network.NetworkManager#markPublicIpAsAllocated(com.cloud.network.IPAddressVO) @@ -939,11 +922,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } - @Override - public boolean removeVmSecondaryIpsOfNic(long nicId) { - // TODO Auto-generated method stub - return false; - } @Override public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index a1ece441863..d46be7c9e22 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -1142,10 +1142,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return false; } - - - - + /* (non-Javadoc) * @see com.cloud.network.NetworkManager#releaseNic(com.cloud.vm.VirtualMachineProfile, com.cloud.vm.Nic) */ @@ -1156,10 +1153,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#createNicForVm(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.ReservationContext, com.cloud.vm.VirtualMachineProfileImpl, boolean, boolean) */ @@ -1172,24 +1165,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } - - - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignVpnGatewayIpAddress(long, com.cloud.user.Account, long) - */ - @Override - public PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) - throws InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - - - - + /* (non-Javadoc) * @see com.cloud.network.NetworkManager#markPublicIpAsAllocated(com.cloud.network.IPAddressVO) */ @@ -1200,9 +1176,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#assignDedicateIpAddress(com.cloud.user.Account, java.lang.Long, java.lang.Long, long, boolean) */ @@ -1240,22 +1213,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#cleanupIpResources(long, long, com.cloud.user.Account) - */ - @Override - public boolean cleanupIpResources(long addrId, long userId, Account caller) { - // TODO Auto-generated method stub - return false; - } - - - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) */ @@ -1435,13 +1392,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - @Override - public boolean removeVmSecondaryIpsOfNic(long nicId) { - // TODO Auto-generated method stub - return false; - } - - @Override public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { // TODO Auto-generated method stub From 560fa52fdcef75df3c8baed69c8610659c1fd1a5 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 28 May 2013 15:57:14 -0700 Subject: [PATCH 181/201] CLOUDSTACK-2678: portable IP ranges - Associate IP Address - pop up a dialog that have cross zone dropdown (yes/no) and send selected option to API call. --- ui/scripts/network.js | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 0ffaa1dce2f..d66ec839dd6 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -1755,18 +1755,36 @@ } }, messages: { + /* confirm: function(args) { if(args.context.vpc) return 'message.acquire.new.ip.vpc'; else return 'message.acquire.new.ip'; }, + */ notification: function(args) { return 'label.acquire.new.ip'; } - }, + }, + createForm: { + title: 'label.acquire.new.ip', + fields: { + isportable: { + label: 'label.cross.zones', + select: function(args) { + var items = []; + items.push({ id: "false", description: _l('label.no') }); + items.push({ id: "true", description: _l('label.yes') }); + args.response.success({data: items}); + } + } + } + }, action: function(args) { - var dataObj = {}; + var dataObj = { + isportable: args.data.isportable + }; if('vpc' in args.context) { //from VPC section $.extend(dataObj, { vpcid: args.context.vpc[0].id @@ -2299,6 +2317,12 @@ ipaddress: { label: 'label.ip' } }, { + isportable: { + label: 'label.cross.zones', + converter: function(data) { + return data ? _l('label.yes') : _l('label.no'); + } + }, id: { label: 'label.id' }, associatednetworkid: { label: 'label.associated.network.id' }, networkname: { label: 'label.associated.network' }, From 6e55776795d2bf3c71f02ee8a38ad29e5d303f9d Mon Sep 17 00:00:00 2001 From: Min Chen Date: Tue, 28 May 2013 15:41:02 -0700 Subject: [PATCH 182/201] CLOUDSTACK-2331: Failed to display exception object information in case of CloudRuntimeException. --- .../org/apache/cloudstack/api/BaseCmd.java | 2 +- .../cloudstack/api/ServerApiException.java | 3 +- .../user/account/AddAccountToProjectCmd.java | 2 +- .../snapshot/CreateSnapshotPolicyCmd.java | 2 +- .../user/template/CreateTemplateCmd.java | 2 +- .../api/response/ExceptionResponse.java | 12 ++- server/src/com/cloud/api/ApiServer.java | 14 +++- .../com/cloud/api/query/QueryManagerImpl.java | 2 +- .../api/response/ApiResponseSerializer.java | 23 ++++-- .../com/cloud/network/NetworkManagerImpl.java | 22 ++--- .../com/cloud/network/NetworkModelImpl.java | 19 ++++- .../com/cloud/network/NetworkServiceImpl.java | 82 +++++++++---------- .../lb/LoadBalancingRulesManagerImpl.java | 27 ++++-- .../cloud/network/rules/RulesManagerImpl.java | 12 +-- .../com/cloud/network/vpc/VpcManagerImpl.java | 16 ++-- .../cloud/projects/ProjectManagerImpl.java | 34 +++++--- .../cloud/resource/ResourceManagerImpl.java | 26 +++--- .../cloud/server/ManagementServerImpl.java | 65 ++++++++------- .../src/com/cloud/user/DomainManagerImpl.java | 10 +-- .../src/com/cloud/vm/UserVmManagerImpl.java | 34 ++++---- .../ApplicationLoadBalancerManagerImpl.java | 2 +- .../exception/CloudRuntimeException.java | 24 +++--- .../utils/exception/ExceptionProxyObject.java | 50 +++++++++++ 23 files changed, 299 insertions(+), 186 deletions(-) create mode 100644 utils/src/com/cloud/utils/exception/ExceptionProxyObject.java diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 9ac110cfb1b..219e7c79e6f 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -521,7 +521,7 @@ public abstract class BaseCmd { return project.getProjectAccountId(); } else { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } } else { diff --git a/api/src/org/apache/cloudstack/api/ServerApiException.java b/api/src/org/apache/cloudstack/api/ServerApiException.java index 4b0fae58548..1a740d56c90 100644 --- a/api/src/org/apache/cloudstack/api/ServerApiException.java +++ b/api/src/org/apache/cloudstack/api/ServerApiException.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import com.cloud.exception.CloudException; import com.cloud.utils.exception.CSExceptionErrorCode; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.ExceptionProxyObject; @SuppressWarnings("serial") public class ServerApiException extends CloudRuntimeException { @@ -45,7 +46,7 @@ public class ServerApiException extends CloudRuntimeException { _description = description; if (cause instanceof CloudRuntimeException) { CloudRuntimeException rt = (CloudRuntimeException) cause; - ArrayList idList = rt.getIdProxyList(); + ArrayList idList = rt.getIdProxyList(); if (idList != null) { for (int i = 0; i < idList.size(); i++) { addProxyObject(idList.get(i)); diff --git a/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java b/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java index ebc22723585..58735f281e9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java @@ -101,7 +101,7 @@ public class AddAccountToProjectCmd extends BaseAsyncCmd { //verify input parameters if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, getProjectId(), "projectId"); + ex.addProxyObject(getProjectId().toString(), "projectId"); throw ex; } diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java index 5a9ea2a073d..14c2ee11c80 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java @@ -112,7 +112,7 @@ public class CreateSnapshotPolicyCmd extends BaseCmd { Project project = _projectService.findByProjectAccountId(volume.getAccountId()); if (project.getState() != Project.State.Active) { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the specified project id in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, project.getId(), "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } } else if (account.getState() == Account.State.disabled) { diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java index 6a482ac1ff2..6aa60aca1fc 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java @@ -207,7 +207,7 @@ import java.util.Map; Project project = _projectService.findByProjectAccountId(accountId); if (project.getState() != Project.State.Active) { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the specified project id in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, project.getId(), "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); } } else if (account.getState() == Account.State.disabled) { throw new PermissionDeniedException("The owner of template is disabled: " + account); diff --git a/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java b/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java index 3afd516e075..830cf007cd0 100644 --- a/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java @@ -17,16 +17,18 @@ package org.apache.cloudstack.api.response; import java.util.ArrayList; +import java.util.List; import org.apache.cloudstack.api.BaseResponse; import com.cloud.serializer.Param; +import com.cloud.utils.exception.ExceptionProxyObject; import com.google.gson.annotations.SerializedName; public class ExceptionResponse extends BaseResponse { @SerializedName("uuidList") @Param(description="List of uuids associated with this error") - private ArrayList idList; + private List idList; @SerializedName("errorcode") @Param(description="numeric code associated with this error") private Integer errorCode; @@ -37,6 +39,10 @@ public class ExceptionResponse extends BaseResponse { @SerializedName("errortext") @Param(description="the text associated with this error") private String errorText = "Command failed due to Internal Server Error"; + public ExceptionResponse(){ + idList = new ArrayList(); + } + public Integer getErrorCode() { return errorCode; } @@ -53,12 +59,12 @@ public class ExceptionResponse extends BaseResponse { this.errorText = errorText; } - public void addProxyObject(String id) { + public void addProxyObject(ExceptionProxyObject id) { idList.add(id); return; } - public ArrayList getIdProxyList() { + public List getIdProxyList() { return idList; } diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 497be50a766..e748a35a747 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -148,6 +148,7 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.ExceptionProxyObject; @Component public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiServerService { @@ -387,9 +388,16 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); } catch (PermissionDeniedException ex){ - ArrayList idList = ex.getIdProxyList(); + ArrayList idList = ex.getIdProxyList(); if (idList != null) { - s_logger.info("PermissionDenied: " + ex.getMessage() + " on uuids: [" + StringUtils.listToCsvTags(idList) + "]"); + StringBuffer buf = new StringBuffer(); + for (ExceptionProxyObject obj : idList){ + buf.append(obj.getDescription()); + buf.append(":"); + buf.append(obj.getUuid()); + buf.append(" "); + } + s_logger.info("PermissionDenied: " + ex.getMessage() + " on objs: [" + buf.toString() + "]"); } else { s_logger.info("PermissionDenied: " + ex.getMessage()); } @@ -1067,7 +1075,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer apiResponse.setErrorCode(ex.getErrorCode().getHttpCode()); apiResponse.setErrorText(ex.getDescription()); apiResponse.setResponseName(responseName); - ArrayList idList = ex.getIdProxyList(); + ArrayList idList = ex.getIdProxyList(); if (idList != null) { for (int i=0; i < idList.size(); i++) { apiResponse.addProxyObject(idList.get(i)); diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index c586a7b19f2..5a25732bca0 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -2176,7 +2176,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { UserVmVO vmInstance = _userVmDao.findById(vmId); if ((vmInstance == null) || (vmInstance.getRemoved() != null)) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a virtual machine with specified id"); - ex.addProxyObject(vmInstance, vmId, "vmId"); + ex.addProxyObject(vmId.toString(), "vmId"); throw ex; } diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java index 965660a52cc..d2e5130931d 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -21,8 +21,10 @@ import com.cloud.api.ApiResponseGsonHelper; import com.cloud.api.ApiServer; import com.cloud.utils.encoding.URLEncoder; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.ExceptionProxyObject; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; + import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ResponseObject; @@ -215,22 +217,27 @@ public class ApiResponseSerializer { subObj.setObjectName(serializedName.value()); } serializeResponseObjXML(sb, subObj); - } else { - // Only exception reponses carry a list of uuid - // strings. + } else if (value instanceof ExceptionProxyObject) { + // Only exception reponses carry a list of + // ExceptionProxyObject objects. + ExceptionProxyObject idProxy = (ExceptionProxyObject) value; // If this is the first IdentityProxy field // encountered, put in a uuidList tag. if (!usedUuidList) { - sb.append("<").append(serializedName.value()).append(">"); + sb.append("<" + serializedName.value() + ">"); usedUuidList = true; } - sb.append("").append(value).append(""); - // We have removed uuid property field due to removal of IdentityProxy class. + sb.append("<" + "uuid" + ">" + idProxy.getUuid() + ""); + // Append the new descriptive property also. + String idFieldName = idProxy.getDescription(); + if (idFieldName != null) { + sb.append("<" + "uuidProperty" + ">" + idFieldName + ""); + } } } if (usedUuidList) { - // close the uuidList. - sb.append(""); + // close the uuidList. + sb.append(""); } } else if (fieldValue instanceof Date) { sb.append("<").append(serializedName.value()).append(">").append(BaseCmd.getDateString((Date) fieldValue)). diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index fda0773147c..cc149a542fd 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -737,7 +737,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // zone is of type DataCenter. See DataCenterVO.java. PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, " + "Zone is currently disabled"); - ex.addProxyObject("data_center", zone.getId(), "zoneId"); + ex.addProxyObject(zone.getUuid(), "zoneId"); throw ex; } @@ -1483,8 +1483,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (errorIfAlreadySetup) { InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)"); - ex.addProxyObject(offering, offering.getId(), "offeringId"); - ex.addProxyObject(configs.get(0), configs.get(0).getId(), "networkConfigId"); + ex.addProxyObject(offering.getUuid(), "offeringId"); + ex.addProxyObject(configs.get(0).getUuid(), "networkConfigId"); throw ex; } else { return configs; @@ -1500,8 +1500,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (errorIfAlreadySetup) { InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)"); - ex.addProxyObject(offering, offering.getId(), "offeringId"); - ex.addProxyObject(configs.get(0), configs.get(0).getId(), "networkConfigId"); + ex.addProxyObject(offering.getUuid(), "offeringId"); + ex.addProxyObject(configs.get(0).getUuid(), "networkConfigId"); throw ex; } else { return configs; @@ -1553,7 +1553,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (networks.size() < 1) { // see networkOfferingVO.java CloudRuntimeException ex = new CloudRuntimeException("Unable to convert network offering with specified id to network profile"); - ex.addProxyObject(offering, offering.getId(), "offeringId"); + ex.addProxyObject(offering.getUuid(), "offeringId"); throw ex; } @@ -1932,7 +1932,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (!element.implement(network, offering, dest, context)) { CloudRuntimeException ex = new CloudRuntimeException("Failed to implement provider " + element.getProvider().getName() + " for network with specified id"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } @@ -2330,7 +2330,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (ntwkOff.getState() != NetworkOffering.State.Enabled) { // see NetworkOfferingVO InvalidParameterValueException ex = new InvalidParameterValueException("Can't use specified network offering id as its stat is not " + NetworkOffering.State.Enabled); - ex.addProxyObject(ntwkOff, ntwkOff.getId(), "networkOfferingId"); + ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); throw ex; } @@ -2339,7 +2339,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // see PhysicalNetworkVO.java InvalidParameterValueException ex = new InvalidParameterValueException("Specified physical network id is" + " in incorrect state:" + pNtwk.getState()); - ex.addProxyObject("physical_network", pNtwk.getId(), "physicalNetworkId"); + ex.addProxyObject(pNtwk.getUuid(), "physicalNetworkId"); throw ex; } @@ -2992,7 +2992,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L NetworkVO network = _networksDao.findById(networkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(String.valueOf(networkId), "networkId"); throw ex; } @@ -3241,7 +3241,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L " network provision due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)" + " elements and resources as a part of network provision for persistent network"); - e.addProxyObject(guestNetwork, guestNetwork.getId(), "networkId"); + e.addProxyObject(guestNetwork.getUuid(), "networkId"); throw e; } } diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 010cb9d5c54..f6bd646a91d 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -37,9 +37,11 @@ import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.api.ApiDBUtils; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; @@ -283,7 +285,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { } else { CloudRuntimeException ex = new CloudRuntimeException("Multiple generic soure NAT IPs provided for network"); // see the IPAddressVO.java class. - ex.addProxyObject("user_ip_address", ip.getAssociatedWithNetworkId(), "networkId"); + IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ip.getAssociatedWithNetworkId()); + String ipAddrUuid = ip.getAssociatedWithNetworkId().toString(); + if ( ipAddr != null){ + ipAddrUuid = ipAddr.getUuid(); + } + ex.addProxyObject(ipAddrUuid, "networkId"); throw ex; } } @@ -1129,17 +1136,21 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { public PhysicalNetwork getDefaultPhysicalNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) { List networkList = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, trafficType); + DataCenter dc = ApiDBUtils.findZoneById(zoneId); + String dcUuid = String.valueOf(zoneId); + if ( dc != null ){ + dcUuid = dc.getUuid(); + } if (networkList.isEmpty()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find the default physical network with traffic=" + trafficType + " in the specified zone id"); - // Since we don't have a DataCenterVO object at our disposal, we just set the table name that the zoneId's corresponding uuid is looked up from, manually. - ex.addProxyObject("data_center", zoneId, "zoneId"); + ex.addProxyObject(dcUuid, "zoneId"); throw ex; } if (networkList.size() > 1) { InvalidParameterValueException ex = new InvalidParameterValueException("More than one physical networks exist in zone id=" + zoneId + " with traffic type=" + trafficType); - ex.addProxyObject("data_center", zoneId, "zoneId"); + ex.addProxyObject(dcUuid, "zoneId"); throw ex; } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 4eed735f255..98992846c4e 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -65,6 +65,7 @@ import org.springframework.stereotype.Component; import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; import org.bouncycastle.util.IPAddress; +import com.cloud.api.ApiDBUtils; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; @@ -317,7 +318,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } else { CloudRuntimeException ex = new CloudRuntimeException("Multiple generic soure NAT IPs provided for network"); // see the IPAddressVO.java class. - ex.addProxyObject("user_ip_address", ip.getAssociatedWithNetworkId(), "networkId"); + IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ip.getAssociatedWithNetworkId()); + String ipAddrUuid = ip.getAssociatedWithNetworkId().toString(); + if ( ipAddr != null ){ + ipAddrUuid = ipAddr.getUuid(); + } + ex.addProxyObject(ipAddrUuid, "networkId"); throw ex; } } @@ -877,7 +883,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // don't allow releasing system ip address if (ipVO.getSystem()) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't release system IP address with specified id"); - ex.addProxyObject(ipVO, ipVO.getId(), "systemIpAddrId"); + ex.addProxyObject(ipVO.getUuid(), "systemIpAddrId"); throw ex; } @@ -994,12 +1000,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (ntwkOff == null || ntwkOff.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering by specified id"); if (ntwkOff != null) { - ex.addProxyObject(ntwkOff, networkOfferingId, "networkOfferingId"); - // Get the VO object's table name. - String tablename = AnnotationHelper.getTableName(ntwkOff); - if (tablename != null) { - ex.addProxyObject(tablename, networkOfferingId, "networkOfferingId"); - } + ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); } throw ex; } @@ -1033,7 +1034,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { // See DataCenterVO.java PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation since specified Zone is currently disabled"); - ex.addProxyObject(zone, zoneId, "zoneId"); + ex.addProxyObject(zone.getUuid(), "zoneId"); throw ex; } @@ -1255,13 +1256,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // Can add vlan range only to the network which allows it if (createVlan && !ntwkOff.getSpecifyIpRanges()) { InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id doesn't support adding multiple ip ranges"); - ex.addProxyObject(ntwkOff, ntwkOff.getId(), "networkOfferingId"); - String tablename = AnnotationHelper.getTableName(ntwkOff); - if (tablename != null) { - ex.addProxyObject(tablename, ntwkOff.getId(), "networkOfferingId"); - } else { - s_logger.info("\nCould not retrieve table name (annotation) from " + tablename + " VO proxy object\n"); - } + ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); throw ex; } @@ -1346,7 +1341,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } catch (ResourceUnavailableException ex) { s_logger.warn("Failed to implement persistent guest network " + network + "due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network"); - e.addProxyObject(network, network.getId(), "networkId"); + e.addProxyObject(network.getUuid(), "networkId"); throw e; } } @@ -1432,7 +1427,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { // getProject() returns type ProjectVO. InvalidParameterValueException ex = new InvalidParameterValueException("Account " + caller + " cannot access specified project id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } permittedAccounts.add(project.getProjectAccountId()); @@ -1757,14 +1752,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // see NetworkVO.java InvalidParameterValueException ex = new InvalidParameterValueException("unable to find network with specified id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(String.valueOf(networkId), "networkId"); throw ex; } // don't allow to delete system network if (isNetworkSystem(network)) { InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id is system and can't be removed"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } @@ -1793,7 +1788,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { NetworkVO network = _networksDao.findById(networkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist"); - ex.addProxyObject("networks", networkId, "networkId"); + ex.addProxyObject(networkId.toString(), "networkId"); throw ex; } @@ -1936,7 +1931,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (network == null) { // see NetworkVO.java InvalidParameterValueException ex = new InvalidParameterValueException("Specified network id doesn't exist in the system"); - ex.addProxyObject("networks", networkId, "networkId"); + ex.addProxyObject(String.valueOf(networkId), "networkId"); throw ex; } @@ -1992,14 +1987,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (networkOfferingId != null) { if (networkOffering == null || networkOffering.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering with specified id"); - ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); + ex.addProxyObject(networkOfferingId.toString(), "networkOfferingId"); throw ex; } // network offering should be in Enabled state if (networkOffering.getState() != NetworkOffering.State.Enabled) { InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id is not in " + NetworkOffering.State.Enabled + " state, can't upgrade to it"); - ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); + ex.addProxyObject(networkOffering.getUuid(), "networkOfferingId"); throw ex; } //can't update from vpc to non-vpc network offering @@ -2021,7 +2016,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (changeCidr) { if (!checkForNonStoppedVmInNetwork(network.getId())) { InvalidParameterValueException ex = new InvalidParameterValueException("All user vm of network of specified id should be stopped before changing CIDR!"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } @@ -2154,7 +2149,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!_networkMgr.shutdownNetworkElementsAndResources(context, true, network)) { s_logger.warn("Failed to shutdown the network elements and resources as a part of network restart: " + network); CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network of specified id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } else { @@ -2173,13 +2168,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!_networkMgr.shutdownNetwork(network.getId(), context, true)) { s_logger.warn("Failed to shutdown the network as a part of update to network with specified id"); CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network as a part of update of specified network id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } } else { CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network with specified id; network is in wrong state: " + network.getState()); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } @@ -2190,7 +2185,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { boolean validStateToImplement = (networkState == Network.State.Implemented || networkState == Network.State.Setup || networkState == Network.State.Allocated); if (restartNetwork && !validStateToImplement) { CloudRuntimeException ex = new CloudRuntimeException("Failed to implement the network elements and resources as a part of update to network with specified id; network is in wrong state: " + networkState); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } @@ -2241,7 +2236,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } catch (Exception ex) { s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network update due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of network update"); - e.addProxyObject(network, networkId, "networkId"); + e.addProxyObject(network.getUuid(), "networkId"); throw e; } } @@ -2259,7 +2254,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { "f network update due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified" + " id) elements and resources as a part of network update"); - e.addProxyObject(network, networkId, "networkId"); + e.addProxyObject(network.getUuid(), "networkId"); throw e; } } @@ -2527,7 +2522,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO network = _physicalNetworkDao.findById(id); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(network, id, "physicalNetworkId"); + ex.addProxyObject(id.toString(), "physicalNetworkId"); throw ex; } @@ -2535,7 +2530,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { DataCenter zone = _dcDao.findById(network.getDataCenterId()); if (zone == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Zone with id=" + network.getDataCenterId() + " doesn't exist in the system"); - ex.addProxyObject(zone, network.getDataCenterId(), "dataCenterId"); + ex.addProxyObject(String.valueOf(network.getDataCenterId()), "dataCenterId"); throw ex; } if (newVnetRangeString != null) { @@ -2804,7 +2799,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (pNetwork == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(pNetwork, physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(physicalNetworkId.toString(), "physicalNetworkId"); throw ex; } @@ -3100,7 +3095,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { Account account = _accountDao.findActiveAccount(accountName, domainId); if (account == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account " + accountName); - ex.addProxyObject("domain", domainId, "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(domainId); + String domainUuid = domainId.toString(); + if (domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } else { accountId = account.getId(); @@ -3112,7 +3112,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { Project project = _projectMgr.getProject(projectId); if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project by id " + projectId); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(projectId.toString(), "projectId"); throw ex; } accountId = project.getProjectAccountId(); @@ -3210,7 +3210,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(network, physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(physicalNetworkId.toString(), "physicalNetworkId"); throw ex; } @@ -3219,7 +3219,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO destNetwork = _physicalNetworkDao.findById(destinationPhysicalNetworkId); if (destNetwork == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Destination Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(destNetwork, destinationPhysicalNetworkId, "destinationPhysicalNetworkId"); + ex.addProxyObject(destinationPhysicalNetworkId.toString(), "destinationPhysicalNetworkId"); throw ex; } } @@ -3646,7 +3646,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(network, physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(physicalNetworkId.toString(), "physicalNetworkId"); throw ex; } @@ -3818,7 +3818,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (pNtwk == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find a physical network" + " having the given id"); - ex.addProxyObject("physical_network", physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(String.valueOf(physicalNetworkId), "physicalNetworkId"); throw ex; } @@ -3912,7 +3912,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (userVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Virtual mahine id does not exist"); - ex.addProxyObject(userVm, vmId, "vmId"); + ex.addProxyObject(vmId.toString(), "vmId"); throw ex; } _accountMgr.checkAccess(caller, null, true, userVm); diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 1d7b3121158..633357e4bdd 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -947,7 +947,11 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements UserVm vm = _vmDao.findById(instanceId); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { InvalidParameterValueException ex = new InvalidParameterValueException("Invalid instance id specified"); - ex.addProxyObject(vm, instanceId, "instanceId"); + if (vm == null) { + ex.addProxyObject(instanceId.toString(), "instanceId"); + } else { + ex.addProxyObject(vm.getUuid(), "instanceId"); + } throw ex; } @@ -971,7 +975,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (nicInSameNetwork == null) { InvalidParameterValueException ex = new InvalidParameterValueException("VM " + instanceId + " cannot be added because it doesn't belong in the same network."); - ex.addProxyObject(vm, instanceId, "instanceId"); + ex.addProxyObject(vm.getUuid(), "instanceId"); throw ex; } @@ -1024,7 +1028,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!success) { CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); // TBD: Also pack in the instanceIds in the exception using the // right VO object or table name. throw ex; @@ -1075,7 +1079,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds); CloudRuntimeException ex = new CloudRuntimeException( "Failed to remove specified load balancer rule id for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); throw ex; } success = true; @@ -1098,7 +1102,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!success) { CloudRuntimeException ex = new CloudRuntimeException( "Failed to remove specified load balancer rule id for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); throw ex; } return success; @@ -1368,12 +1372,17 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (ipAddr == null || !ipAddr.readyToUse()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to create load balancer rule, invalid IP address id specified"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + if (ipAddr == null){ + ex.addProxyObject(String.valueOf(sourceIpId), "sourceIpId"); + } + else{ + ex.addProxyObject(ipAddr.getUuid(), "sourceIpId"); + } throw ex; } else if (ipAddr.isOneToOneNat()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to create load balancer rule; specified sourceip id has static nat enabled"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + ex.addProxyObject(ipAddr.getUuid(), "sourceIpId"); throw ex; } @@ -1384,7 +1393,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (networkId == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to create load balancer rule ; specified sourceip id is not associated with any network"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + ex.addProxyObject(ipAddr.getUuid(), "sourceIpId"); throw ex; } @@ -2083,7 +2092,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { InvalidParameterValueException ex = new InvalidParameterValueException( "LB service is not supported in specified network id"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 3c95cef440f..dd5f99ba574 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -1257,14 +1257,14 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules if (ipAddress.getSystem()) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't disable static nat for system IP address with specified id"); - ex.addProxyObject(ipAddress, ipId, "ipId"); + ex.addProxyObject(ipAddress.getUuid(), "ipId"); throw ex; } Long vmId = ipAddress.getAssociatedWithVmId(); if (vmId == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Specified IP address id is not associated with any vm Id"); - ex.addProxyObject(ipAddress, ipId, "ipId"); + ex.addProxyObject(ipAddress.getUuid(), "ipId"); throw ex; } @@ -1292,7 +1292,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules if (!ipAddress.isOneToOneNat()) { InvalidParameterValueException ex = new InvalidParameterValueException("One to one nat is not enabled for the specified ip id"); - ex.addProxyObject(ipAddress, ipId, "ipId"); + ex.addProxyObject(ipAddress.getUuid(), "ipId"); throw ex; } @@ -1353,14 +1353,14 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules if (ip == null || !ip.isOneToOneNat() || ip.getAssociatedWithVmId() == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Source ip address of the specified firewall rule id is not static nat enabled"); - ex.addProxyObject(ruleVO, rule.getId(), "ruleId"); + ex.addProxyObject(ruleVO.getUuid(), "ruleId"); throw ex; } String dstIp = ip.getVmIp(); if (dstIp == null) { InvalidParameterValueException ex = new InvalidParameterValueException("VM ip address of the specified public ip is not set "); - ex.addProxyObject(ruleVO, rule.getId(), "ruleId"); + ex.addProxyObject(ruleVO.getUuid(), "ruleId"); throw ex; } @@ -1432,7 +1432,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules Network network = _networkModel.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"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 15e1539ae7d..380a95e1882 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -587,7 +587,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (vpcOff == null || vpcOff.getState() != State.Enabled) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find vpc offering in " + State.Enabled + " state by specified id"); - ex.addProxyObject("vpc_offerings", vpcOffId, "vpcOfferingId"); + if (vpcOff == null) { + ex.addProxyObject(String.valueOf(vpcOffId), "vpcOfferingId"); + } else { + ex.addProxyObject(vpcOff.getUuid(), "vpcOfferingId"); + } throw ex; } @@ -596,7 +600,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { // See DataCenterVO.java PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation since specified Zone is currently disabled"); - ex.addProxyObject("data_center", zone.getId(), "zoneId"); + ex.addProxyObject(zone.getUuid(), "zoneId"); throw ex; } @@ -943,7 +947,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } @@ -1275,7 +1279,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } @@ -1354,7 +1358,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } @@ -2016,7 +2020,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC "); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } _accountMgr.checkAccess(caller, null, false, vpc); diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index de4f3ccd11b..7ab385f2de4 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -43,6 +43,7 @@ import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.api.ApiDBUtils; import com.cloud.api.query.dao.ProjectAccountJoinDao; import com.cloud.api.query.dao.ProjectInvitationJoinDao; import com.cloud.api.query.dao.ProjectJoinDao; @@ -50,6 +51,7 @@ import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; @@ -508,14 +510,14 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } //User can be added to Active project only if (project.getState() != Project.State.Active) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't add account to the specified project id in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(),"projectId"); throw ex; } @@ -525,8 +527,12 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { account = _accountMgr.getActiveAccountByName(accountName, project.getDomainId()); if (account == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account name=" + accountName + " in specified domain id"); - // We don't have a DomainVO object with us, so just pass the tablename "domain" manually. - ex.addProxyObject("domain", project.getDomainId(), "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(project.getDomainId()); + String domainUuid = String.valueOf(project.getDomainId()); + if ( domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } @@ -590,7 +596,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } @@ -598,8 +604,12 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { Account account = _accountMgr.getActiveAccountByName(accountName, project.getDomainId()); if (account == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account name=" + accountName + " in domain id=" + project.getDomainId()); - // Since we don't have a domainVO object, pass the table name manually. - ex.addProxyObject("domain", project.getDomainId(), "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(project.getDomainId()); + String domainUuid = String.valueOf(project.getDomainId()); + if ( domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); } //verify permissions @@ -610,14 +620,14 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (projectAccount == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Account " + accountName + " is not assigned to the project with specified id"); // Use the projectVO object and not the projectAccount object to inject the projectId. - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } //can't remove the owner of the project if (projectAccount.getAccountRole() == Role.Admin) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to delete account " + accountName + " from the project with specified id as the account is the owner of the project"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } @@ -791,7 +801,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } @@ -833,7 +843,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { //verify input parameters if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } @@ -844,7 +854,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { return _projectDao.findById(projectId); } else { CloudRuntimeException ex = new CloudRuntimeException("Failed to suspend project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 13780d2756b..f767b6810a4 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -391,7 +391,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (zone == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Can't find zone by the id specified"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(String.valueOf(dcId), "dcId"); throw ex; } @@ -400,7 +400,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, && !_accountMgr.isRootAdmin(account.getType())) { PermissionDeniedException ex = new PermissionDeniedException( "Cannot perform this operation, Zone with specified id is currently disabled"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -419,8 +419,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) { InvalidParameterValueException ex = new InvalidParameterValueException( "Pod with specified id doesn't belong to the zone " + dcId); - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -504,8 +504,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, "Unable to create cluster " + clusterName + " in pod and data center with specified ids", e); // Get the pod VO object's table name. - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } clusterId = cluster.getId(); @@ -639,7 +639,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (cluster == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "can not find cluster for specified clusterId"); - ex.addProxyObject(cluster, clusterId, "clusterId"); + ex.addProxyObject(clusterId.toString(), "clusterId"); throw ex; } else { if (cluster.getGuid() == null) { @@ -647,7 +647,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (!hosts.isEmpty()) { CloudRuntimeException ex = new CloudRuntimeException( "Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up"); - ex.addProxyObject(cluster, clusterId, "clusterId"); + ex.addProxyObject(cluster.getUuid(), "clusterId"); throw ex; } } @@ -703,7 +703,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, && !_accountMgr.isRootAdmin(account.getType())) { PermissionDeniedException ex = new PermissionDeniedException( "Cannot perform this operation, Zone with specified id is currently disabled"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -721,8 +721,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + podId + " doesn't belong to the zone with specified zoneId" + dcId); - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } } @@ -792,8 +792,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + clusterName + " in pod with specified podId and data center with specified dcID", e); - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 8323af84981..d5d95f8eadb 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1153,7 +1153,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, cannot " + "migrate the vm with specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -1174,8 +1174,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to find the host (with specified id) of VM with specified id"); - ex.addProxyObject(srcHost, srcHostId, "hostId"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(srcHostId), "hostId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -1331,7 +1331,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (volume == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with" + " specified id."); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volumeId.toString(), "volumeId"); throw ex; } @@ -1585,8 +1585,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe + " in specified domain"); // Since we don't have a DomainVO object here, we directly set // tablename to "domain". - String tablename = "domain"; - ex.addProxyObject(tablename, domainId, "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(domainId); + String domainUuid = domainId.toString(); + if ( domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } else { accountId = account.getId(); @@ -1606,7 +1610,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Project project = _projectMgr.getProject(projectId); if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project by id " + projectId); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(projectId.toString(), "projectId"); throw ex; } accountId = project.getProjectAccountId(); @@ -1840,14 +1844,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (isIso && template.getFormat() != ImageFormat.ISO) { s_logger.error("Template Id " + templateId + " is not an ISO"); InvalidParameterValueException ex = new InvalidParameterValueException("Specified Template Id is not an ISO"); - ex.addProxyObject(template, templateId, "templateId"); + ex.addProxyObject(template.getUuid(), "templateId"); throw ex; }// If ISO not requested then it shouldn't be an ISO. if (!isIso && template.getFormat() == ImageFormat.ISO) { s_logger.error("Incorrect format of the template id " + templateId); InvalidParameterValueException ex = new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the specified template id"); - ex.addProxyObject(template, templateId, "templateId"); + ex.addProxyObject(template.getUuid(), "templateId"); throw ex; } } @@ -1951,14 +1955,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMTemplateVO template = _templateDao.findById(id); if (template == null || template.getRemoved() != null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find template/iso with specified id"); - ex.addProxyObject(template, id, "templateId"); + ex.addProxyObject(id.toString(), "templateId"); throw ex; } // Don't allow to modify system template if (id.equals(Long.valueOf(1))) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update template/iso of specified id"); - ex.addProxyObject(template, id, "templateId"); + ex.addProxyObject(template.getUuid(), "templateId"); throw ex; } @@ -2306,7 +2310,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe DomainVO domain = _domainDao.findById(domainId); if (domain == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find domain with specified domain id"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domainId.toString(), "domainId"); throw ex; } else if (domain.getParent() == null && domainName != null) { // check if domain is ROOT domain - and deny to edit it with the new @@ -2330,7 +2334,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (!domains.isEmpty() && !sameDomain) { InvalidParameterValueException ex = new InvalidParameterValueException("Failed to update specified domain id with name '" + domainName + "' since it already exists in the system"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domain.getUuid(), "domainId"); throw ex; } } @@ -3236,7 +3240,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find a system vm of specified instanceId"); - ex.addProxyObject(systemVm, instanceId, "instanceId"); + ex.addProxyObject(String.valueOf(instanceId), "instanceId"); throw ex; } return systemVm.getType(); @@ -3248,7 +3252,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(vmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(vmId), "vmId"); throw ex; } @@ -3258,7 +3262,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return startSecondaryStorageVm(vmId); } else { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, vmId, "vmId"); + ex.addProxyObject(systemVm.getUuid(), "vmId"); throw ex; } } @@ -3271,7 +3275,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, id, "vmId"); + ex.addProxyObject(id.toString(), "vmId"); throw ex; } @@ -3293,7 +3297,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, cmd.getId(), "vmId"); + ex.addProxyObject(cmd.getId().toString(), "vmId"); throw ex; } @@ -3310,7 +3314,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, cmd.getId(), "vmId"); + ex.addProxyObject(cmd.getId().toString(), "vmId"); throw ex; } @@ -3348,7 +3352,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe User user = _accountMgr.getUserIncludingRemoved(userId); if ((user == null) || (user.getRemoved() != null)) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find active user of specified id"); - ex.addProxyObject(user, userId, "userId"); + ex.addProxyObject(String.valueOf(userId), "userId"); throw ex; } @@ -3444,7 +3448,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VolumeVO volume = _volumeDao.findById(volumeId); if (volume == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with specified volumeId"); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volumeId.toString(), "volumeId"); throw ex; } @@ -3464,7 +3468,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe + ". It should be either detached or the VM should be in stopped state."); PermissionDeniedException ex = new PermissionDeniedException( "Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state."); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volume.getUuid(), "volumeId"); throw ex; } @@ -3481,7 +3485,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (!isExtractable && account != null && account.getType() != Account.ACCOUNT_TYPE_ADMIN) { // Global // admins are always allowed to extract PermissionDeniedException ex = new PermissionDeniedException("The volume with specified volumeId is not allowed to be extracted"); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volume.getUuid(), "volumeId"); throw ex; } } @@ -3639,7 +3643,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue()); if (group == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a vm group with specified groupId"); - ex.addProxyObject(group, groupId, "groupId"); + ex.addProxyObject(groupId.toString(), "groupId"); throw ex; } @@ -3845,7 +3849,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (s == null) { InvalidParameterValueException ex = new InvalidParameterValueException("A key pair with name '" + cmd.getName() + "' does not exist for account " + owner.getAccountName() + " in specified domain id"); - ex.addProxyObject(owner, owner.getDomainId(), "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(owner.getDomainId()); + String domainUuid = String.valueOf(owner.getDomainId()); + if (domain != null){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } @@ -3932,7 +3941,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe UserVmVO vm = _userVmDao.findById(cmd.getId()); if (vm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("No VM with specified id found."); - ex.addProxyObject(vm, cmd.getId(), "vmId"); + ex.addProxyObject(cmd.getId().toString(), "vmId"); throw ex; } @@ -3943,7 +3952,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe String password = vm.getDetail("Encrypted.Password"); if (password == null || password.equals("")) { InvalidParameterValueException ex = new InvalidParameterValueException("No password for VM with specified id found."); - ex.addProxyObject(vm, cmd.getId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -4053,7 +4062,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (hpvCapabilities == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find the hypervisor capabilities for specified id"); - ex.addProxyObject(hpvCapabilities, id, "Id"); + ex.addProxyObject(id.toString(), "Id"); throw ex; } diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index c451041d951..00a779e2ff9 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -226,7 +226,7 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom if ((cleanup != null) && cleanup.booleanValue()) { if (!cleanupDomain(domain.getId(), ownerId)) { CloudRuntimeException e = new CloudRuntimeException("Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domain.getId() + ")."); - e.addProxyObject(domain, domain.getId(), "domainId"); + e.addProxyObject(domain.getUuid(), "domainId"); throw e; } } else { @@ -235,13 +235,13 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom if (!_domainDao.remove(domain.getId())) { rollBackState = true; CloudRuntimeException e = new CloudRuntimeException("Delete failed on domain " + domain.getName() + " (id: " + domain.getId() + "); Please make sure all users and sub domains have been removed from the domain before deleting"); - e.addProxyObject(domain, domain.getId(), "domainId"); + e.addProxyObject(domain.getUuid(), "domainId"); throw e; } } else { rollBackState = true; CloudRuntimeException e = new CloudRuntimeException("Can't delete the domain yet because it has " + accountsForCleanup.size() + "accounts that need a cleanup"); - e.addProxyObject(domain, domain.getId(), "domainId"); + e.addProxyObject(domain.getUuid(), "domainId"); throw e; } } @@ -480,7 +480,7 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom DomainVO domain = _domainDao.findById(domainId); if (domain == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find domain with specified domain id"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domainId.toString(), "domainId"); throw ex; } else if (domain.getParent() == null && domainName != null) { // check if domain is ROOT domain - and deny to edit it with the new name @@ -501,7 +501,7 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom if (!domains.isEmpty() && !sameDomain) { InvalidParameterValueException ex = new InvalidParameterValueException("Failed to update specified domain id with name '" + domainName + "' since it already exists in the system"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domain.getUuid(), "domainId"); throw ex; } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 96b95293b47..56578776b98 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -3288,7 +3288,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } catch (CloudException e) { CloudRuntimeException ex = new CloudRuntimeException( "Unable to destroy with specified vmId", e); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3315,7 +3315,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } else { CloudRuntimeException ex = new CloudRuntimeException( "Failed to destroy vm with specified vmId"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } } @@ -3508,7 +3508,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (userVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "unable to find a virtual machine with specified id"); - ex.addProxyObject(userVm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(vmId), "vmId"); throw ex; } @@ -3550,7 +3550,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (vm.getState() != State.Stopped) { InvalidParameterValueException ex = new InvalidParameterValueException( "VM is not Stopped, unable to migrate the vm having the specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3627,7 +3627,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } InvalidParameterValueException ex = new InvalidParameterValueException( "VM is not Running, unable to migrate the vm with specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } if (!vm.getHypervisorType().equals(HypervisorType.XenServer) @@ -3719,7 +3719,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } CloudRuntimeException ex = new CloudRuntimeException("VM is not Running, unable to migrate the vm with" + " specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3849,7 +3849,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } InvalidParameterValueException ex = new InvalidParameterValueException( "VM is Running, unable to move the vm with specified vmId"); - ex.addProxyObject(vm, cmd.getVmId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3863,7 +3863,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (oldAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) { InvalidParameterValueException ex = new InvalidParameterValueException( "Specified Vm id belongs to the project and can't be moved"); - ex.addProxyObject(vm, cmd.getVmId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } Account newAccount = _accountService.getActiveAccountByName( @@ -4116,7 +4116,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to find specified network id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(networkId.toString(), "networkId"); throw ex; } @@ -4129,7 +4129,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (networkOffering.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Specified Network id is system only and can't be used for vm deployment"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } applicableNetworks.add(network); @@ -4180,7 +4180,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use " resources as a part of network provision for persistent network due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network" + " (with specified id) elements and resources as a part of network provision"); - e.addProxyObject(newNetwork, newNetwork.getId(), "networkId"); + e.addProxyObject(newNetwork.getUuid(), "networkId"); throw e; } } @@ -4241,7 +4241,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use UserVmVO vm = _vmDao.findById(vmId); if (vm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Cannot find VM with ID " + vmId); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(vmId), "vmId"); throw ex; } @@ -4287,7 +4287,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (rootVols.isEmpty()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Can not find root volume for VM " + vm.getUuid()); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -4322,8 +4322,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (template == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Cannot find template/ISO for specified volumeid and vmId"); - ex.addProxyObject(vm, vmId, "vmId"); - ex.addProxyObject(root, root.getId(), "volumeId"); + ex.addProxyObject(vm.getUuid(), "vmId"); + ex.addProxyObject(root.getUuid(), "volumeId"); throw ex; } } @@ -4335,7 +4335,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.debug("Stop vm " + vm.getUuid() + " failed", e); CloudRuntimeException ex = new CloudRuntimeException( "Stop vm failed for specified vmId"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } } @@ -4396,7 +4396,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.debug("Unable to start VM " + vm.getUuid(), e); CloudRuntimeException ex = new CloudRuntimeException( "Unable to start VM with specified id" + e.getMessage()); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } } diff --git a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java index ec0be8c9d96..ac3b8f56e61 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -201,7 +201,7 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { InvalidParameterValueException ex = new InvalidParameterValueException( "LB service is not supported in specified network id"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } diff --git a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java index 00141f24122..d3b4c197e14 100755 --- a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java +++ b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java @@ -18,7 +18,6 @@ package com.cloud.utils.exception; import java.util.ArrayList; -import com.cloud.utils.AnnotationHelper; import com.cloud.utils.SerialVersionUID; /** @@ -28,8 +27,8 @@ public class CloudRuntimeException extends RuntimeException { private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; - // This holds a list of uuids and their names. Add uuid:fieldname pairs - protected ArrayList idList = new ArrayList(); + // This holds a list of uuids and their descriptive names. + protected ArrayList idList = new ArrayList(); protected int csErrorCode; @@ -49,21 +48,20 @@ public class CloudRuntimeException extends RuntimeException { setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); } + public void addProxyObject(ExceptionProxyObject obj){ + idList.add(obj); + } + public void addProxyObject(String uuid) { - idList.add(uuid); - return; + idList.add(new ExceptionProxyObject(uuid, null)); } - public void addProxyObject(Object voObj, Long id, String idFieldName) { - // Get the VO object's table name. - String tablename = AnnotationHelper.getTableName(voObj); - if (tablename != null) { - addProxyObject(tablename, id, idFieldName); - } - return; + public void addProxyObject(String voObjUuid, String description) { + ExceptionProxyObject proxy = new ExceptionProxyObject(voObjUuid, description); + idList.add(proxy); } - public ArrayList getIdProxyList() { + public ArrayList getIdProxyList() { return idList; } diff --git a/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java b/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java new file mode 100644 index 00000000000..01cbd632c14 --- /dev/null +++ b/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java @@ -0,0 +1,50 @@ +// 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. +package com.cloud.utils.exception; + + +public class ExceptionProxyObject { + private String uuid; + private String description; + + public ExceptionProxyObject(){ + + } + + public ExceptionProxyObject(String uuid, String desc){ + this.uuid = uuid; + this.description = desc; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + +} From ab2e3b9e07c0da623011859ef73388b5ce0c11ce Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 28 May 2013 16:16:34 -0700 Subject: [PATCH 183/201] CLOUDSTACK-2678: portable IP ranges - regions menu - region detailView - show "View Portable IP Ranges" for root-admin, hide it for regular-user/domain-admin. --- ui/scripts/regions.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index b9b6daeac20..4be600f8b69 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -117,8 +117,20 @@ detailView: { name: 'Region details', viewAll: [ - { path: 'regions.GSLB', label: 'GSLB' }, - { path: 'regions.portableIpRanges', label: 'Portable IP' } + { + path: 'regions.GSLB', + label: 'GSLB' + }, + { + path: 'regions.portableIpRanges', + label: 'Portable IP', + preFilter: function(args) { + if (isAdmin()) + return true; + + return false; + } + } ], actions: { edit: { From ccac84c469607768665cd2239abfdf8bf0561f21 Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Tue, 28 May 2013 17:05:51 -0700 Subject: [PATCH 184/201] Workaround for broken bvt/ simulator tests Actually this check makes no sense since it breaks basic zone for all hypervisors except KVM, XS Will revisit later --- server/src/com/cloud/resource/ResourceManagerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index f767b6810a4..1e28d92896f 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -445,7 +445,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (zone.isSecurityGroupEnabled()) { - if( hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer ) { + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer + && hypervisorType != HypervisorType.Simulator) { throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone"); } } From be5639f7e278aca722757475139a61b69df0163c Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Wed, 29 May 2013 09:48:25 +0530 Subject: [PATCH 185/201] Adding environment attributes to tests - test_internal_lb _ test_privategw_acl Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_internal_lb.py | 2 ++ test/integration/smoke/test_privategw_acl.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py index ae64297bf1c..6c039004ab5 100644 --- a/test/integration/smoke/test_internal_lb.py +++ b/test/integration/smoke/test_internal_lb.py @@ -22,6 +22,7 @@ from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * +from nose.plugins.attrib import attr class TestInternalLb(cloudstackTestCase): @@ -97,6 +98,7 @@ class TestInternalLb(cloudstackTestCase): + @attr(tags=["simulator", "advanced"]) def test_internallb(self): #1) Create and enable network offering with Internal Lb vm service diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index 5daf6ca0a59..af5c28b5b2b 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -22,6 +22,7 @@ from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * +from nose.plugins.attrib import attr class TestPrivateGwACL(cloudstackTestCase): @@ -37,6 +38,8 @@ class TestPrivateGwACL(cloudstackTestCase): self.templateId = 5 self.privateGwId = None + + @attr(tags=["simulator", "advanced"]) def test_privategw_acl(self): # 1) Create VPC From 7fb6eaa0ca5f0f58b23ab6af812db6366743717a Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Wed, 29 May 2013 10:01:20 +0530 Subject: [PATCH 186/201] Attributes for tests Removing simulator attribute as the NetworkACL related support is to be extended on the simulator. Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_internal_lb.py | 2 +- test/integration/smoke/test_network_acl.py | 3 ++- test/integration/smoke/test_privategw_acl.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py index 6c039004ab5..07a539592ca 100644 --- a/test/integration/smoke/test_internal_lb.py +++ b/test/integration/smoke/test_internal_lb.py @@ -98,7 +98,7 @@ class TestInternalLb(cloudstackTestCase): - @attr(tags=["simulator", "advanced"]) + @attr(tags=["advanced"]) def test_internallb(self): #1) Create and enable network offering with Internal Lb vm service diff --git a/test/integration/smoke/test_network_acl.py b/test/integration/smoke/test_network_acl.py index 66f0a6fc1c5..3ed45be9cd0 100644 --- a/test/integration/smoke/test_network_acl.py +++ b/test/integration/smoke/test_network_acl.py @@ -22,7 +22,7 @@ from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * - +from nose.plugins.attrib import attr class TestNetworkACL(cloudstackTestCase): networkOfferingId = 11 @@ -40,6 +40,7 @@ class TestNetworkACL(cloudstackTestCase): + @attr(tags=["advanced"]) def test_networkAcl(self): # 1) Create VPC diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index af5c28b5b2b..9c37e5e7fc0 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -39,7 +39,7 @@ class TestPrivateGwACL(cloudstackTestCase): self.privateGwId = None - @attr(tags=["simulator", "advanced"]) + @attr(tags=["advanced"]) def test_privategw_acl(self): # 1) Create VPC From 84d904abf2e6e0616a47b338e588276530094d4e Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Wed, 29 May 2013 14:20:21 +0530 Subject: [PATCH 187/201] CLOUDSTACK-2719: Additional public IP is getting acquired during Cisco VNMc provider Guest Network restart (cleanup=true) An extra public ip is acquired while implementing the vnmc element as there is a limitation where in the source nat cannot be used as asa outside ip. As a result of this when the network gets re-implemented an additional ip is acquired every time. The fix involves checking for existing public ips in the network and reuse it in case it is not a source nat ip for assigning to asa outside interface. --- .../network/element/CiscoVnmcElement.java | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java index b335edb9f63..9118bad6afe 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java @@ -98,6 +98,8 @@ import com.cloud.network.cisco.NetworkAsa1000vMapVO; import com.cloud.network.dao.CiscoAsa1000vDao; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; import com.cloud.network.dao.CiscoVnmcDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkAsa1000vMapDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.PhysicalNetworkDao; @@ -148,7 +150,9 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro PhysicalNetworkDao _physicalNetworkDao; @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; - @Inject + @Inject + IPAddressDao _ipAddressDao; + @Inject HostDetailsDao _hostDetailsDao; @Inject HostDao _hostDao; @@ -342,22 +346,33 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro } // due to VNMC limitation of not allowing source NAT ip as the outside ip of firewall, - // an additional public ip needs to acquired for assigning as firewall outside ip + // an additional public ip needs to acquired for assigning as firewall outside ip. + // In case there are already additional ip addresses available (network restart) use one + // of them such that it is not the source NAT ip IpAddress outsideIp = null; - try { - Account caller = UserContext.current().getCaller(); - long callerUserId = UserContext.current().getCallerUserId(); - outsideIp = _networkMgr.allocateIp(owner, false, caller, callerUserId, zone); - } catch (ResourceAllocationException e) { - s_logger.error("Unable to allocate additional public Ip address. Exception details " + e); - return false; + List publicIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); + for (IPAddressVO ip : publicIps) { + if (!ip.isSourceNat()) { + outsideIp = ip; + break; + } } + if (outsideIp == null) { // none available, acquire one + try { + Account caller = UserContext.current().getCaller(); + long callerUserId = UserContext.current().getCallerUserId(); + outsideIp = _networkMgr.allocateIp(owner, false, caller, callerUserId, zone); + } catch (ResourceAllocationException e) { + s_logger.error("Unable to allocate additional public Ip address. Exception details " + e); + return false; + } - try { - outsideIp = _networkMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true); - } catch (ResourceAllocationException e) { - s_logger.error("Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); - return false; + try { + outsideIp = _networkMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true); + } catch (ResourceAllocationException e) { + s_logger.error("Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); + return false; + } } // create logical edge firewall in VNMC From e3a104aa58082521dac2a92a9cc1c5b23494f29b Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Wed, 29 May 2013 17:14:36 +0530 Subject: [PATCH 188/201] fix networkAclServiceTest failure --- server/test/com/cloud/vpc/NetworkACLServiceTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/test/com/cloud/vpc/NetworkACLServiceTest.java b/server/test/com/cloud/vpc/NetworkACLServiceTest.java index 9a368b94ae4..e71fabfef2d 100644 --- a/server/test/com/cloud/vpc/NetworkACLServiceTest.java +++ b/server/test/com/cloud/vpc/NetworkACLServiceTest.java @@ -138,6 +138,7 @@ public class NetworkACLServiceTest extends TestCase{ Mockito.when(_networkAclMgr.getNetworkACL(Mockito.anyLong())).thenReturn(acl); Mockito.when(_networkAclMgr.createNetworkACLItem(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyString(), Mockito.anyList(), Mockito.anyInt(), Mockito.anyInt(), Mockito.any(NetworkACLItem.TrafficType.class), Mockito.anyLong(), Mockito.anyString(), Mockito.anyInt())).thenReturn(new NetworkACLItemVO()); + Mockito.when(_networkACLItemDao.findByAclAndNumber(Mockito.anyLong(), Mockito.anyInt())).thenReturn(null); assertNotNull(_aclService.createNetworkACLItem(createACLItemCmd)); } From 2b9396982323e17116515806836cd2f615968557 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 29 May 2013 15:48:13 +0530 Subject: [PATCH 189/201] add upgrade path to "cloud.dns.name" global config value. fail creating GSLB rule if DNS name is not confiugred --- server/src/com/cloud/configuration/Config.java | 2 +- .../region/gslb/GlobalLoadBalancingRulesServiceImpl.java | 3 ++- setup/db/db/schema-410to420.sql | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index e1d3751f290..7c88aae5044 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -408,7 +408,7 @@ public enum Config { VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null), VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null), - CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", "default", " DNS name of the cloud", null), + CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", null, "DNS name of the cloud for the GSLB service", null), BlacklistedRoutes("Advanced", VpcManager.class, String.class, "blacklisted.routes", null, "Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway", "routes", ConfigurationParameterScope.zone.toString()), diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index a1865c64af7..a803f9fb16b 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -126,7 +126,8 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR throw new InvalidParameterValueException("Invalid region ID: " + regionId); } - if (!region.checkIfServiceEnabled(Region.Service.Gslb)) { + String providerDnsName = _globalConfigDao.getValue(Config.CloudDnsName.key()); + if (!region.checkIfServiceEnabled(Region.Service.Gslb) || (providerDnsName == null)) { throw new CloudRuntimeException("GSLB service is not enabled in region : " + region.getName()); } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index cf4e98dc8a0..ec79237de5e 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -332,6 +332,8 @@ CREATE TABLE `cloud`.`global_load_balancer_lb_rule_map` ( CONSTRAINT `fk_lb_rule_id` FOREIGN KEY(`lb_rule_id`) REFERENCES `load_balancing_rules`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'cloud.dns.name', null, 'DNS name of the cloud for the GSLB service'); + INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.cpus', '40', 'The default maximum number of cpu cores that can be used for an account'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.memory', '40960', 'The default maximum memory (in MiB) that can be used for an account'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.primary.storage', '200', 'The default maximum primary storage space (in GiB) that can be used for an account'); From c8a0c40a2f50fdabab085a0d6896edcdb8226ef4 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 29 May 2013 17:01:54 +0530 Subject: [PATCH 190/201] CLOUDSTACK-2477: [GSLB] CloudStack currently allows admin to map LB rule of one account to GSLB rule of a different account ensuring account id of GSLB rule and LB rule are same --- .../region/gslb/GlobalLoadBalancingRulesServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index a803f9fb16b..96ac76e3eae 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -204,6 +204,10 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR _accountMgr.checkAccess(caller, null, true, loadBalancer); + if (gslbRule.getAccountId() != loadBalancer.getAccountId()) { + throw new InvalidParameterValueException("GSLB rule and load balancer rule does not belong to same account"); + } + if (loadBalancer.getState() == LoadBalancer.State.Revoke) { throw new InvalidParameterValueException("Load balancer ID " + loadBalancer.getUuid() + " is in revoke state"); } From ee317287b3981200ec1a54ee096600fd24a16475 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 29 May 2013 18:50:06 +0530 Subject: [PATCH 191/201] CLOUDSTACK-2285: [GSLB] addNetscalerLoadBalancer with GSLB functionality shouldn't be exposed in basic zone imposing restriction that NetScaler can only be added when EIP/ELB service are available in basic zone. --- .../ExternalLoadBalancerDeviceManagerImpl.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index f93bf7ae9b5..04f96825abb 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -138,6 +138,8 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase @Inject NetworkManager _networkMgr; @Inject + NetworkDao _networksDao = null; + @Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; @Inject NicDao _nicDao; @@ -208,6 +210,17 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase } zoneId = pNetwork.getDataCenterId(); + DataCenter dc = _dcDao.findById(zoneId); + if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { + List guestNetworks = _networksDao.listByZoneAndTrafficType(dc.getId(), TrafficType.Guest); + com.cloud.network.dao.NetworkVO basicZoneNetwork = guestNetworks.get(0); + NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(basicZoneNetwork.getNetworkOfferingId()); + if (!ntwkOff.getElasticIp() && !ntwkOff.getElasticLb()) { + throw new InvalidParameterValueException("Could not add external load balancer device in to basic zone " + + " with no Elastic IP and Elastic LB services."); + } + } + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); if (gslbProvider) { From cea9e3919a613c71da5d95acf631355ab2b6d018 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 29 May 2013 18:52:12 +0530 Subject: [PATCH 192/201] fixing unit tests to comply with bug "CLOUDSTACK-2477: [GSLB] CloudStack currently allows admin to map LB rule of one account to GSLB rule of a different account" --- .../GlobalLoadBalancingRulesServiceImplTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java index 1c281a08bed..ab545342cfa 100644 --- a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java +++ b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java @@ -577,8 +577,14 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { LoadBalancerVO lbRule1 = new LoadBalancerVO(); lbRule1.setState(FirewallRule.State.Active); Field networkIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + Field accountIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("accountId"); + Field domainIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("domainId"); networkIdField1.setAccessible(true); + accountIdField1.setAccessible(true); + domainIdField1.setAccessible(true); networkIdField1.set(lbRule1, new Long(1)); + accountIdField1.set(lbRule1, new Long(3)); + domainIdField1.set(lbRule1, new Long(1)); Field idField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); idField1.setAccessible(true); idField1.set(lbRule1, new Long(1)); @@ -586,8 +592,14 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { LoadBalancerVO lbRule2 = new LoadBalancerVO(); lbRule2.setState(FirewallRule.State.Active); Field networkIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + Field accountIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("accountId"); + Field domainIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("domainId"); networkIdField2.setAccessible(true); + accountIdField2.setAccessible(true); + domainIdField2.setAccessible(true); networkIdField2.set(lbRule2, new Long(1)); + accountIdField2.set(lbRule2, new Long(3)); + domainIdField2.set(lbRule2, new Long(1)); Field idField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); idField2.setAccessible(true); idField2.set(lbRule2, new Long(2)); @@ -611,6 +623,7 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { try { gslbServiceImpl.assignToGlobalLoadBalancerRule(assignCmd); } catch (InvalidParameterValueException e) { + s_logger.info(e.getMessage()); Assert.assertTrue(e.getMessage().contains("Load balancer rule specified should be in unique zone")); } } From 8d1189c2ae87216bc1c4a1443f75e9a8629abdc2 Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Wed, 29 May 2013 19:01:23 +0530 Subject: [PATCH 193/201] CLOUDSTACK-2060 Global config to turn off dynamically scale vm functionality --- api/src/com/cloud/agent/api/to/VirtualMachineTO.java | 9 +++++++++ .../hypervisor/xen/resource/XenServer56FP1Resource.java | 2 +- server/src/com/cloud/configuration/Config.java | 3 ++- server/src/com/cloud/hypervisor/HypervisorGuruBase.java | 9 ++++++++- server/src/com/cloud/vm/UserVmManagerImpl.java | 8 ++++++++ setup/db/db/schema-410to420.sql | 4 ++++ 6 files changed, 32 insertions(+), 3 deletions(-) diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java index b84d20a9239..46ee01bc8a3 100644 --- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -52,6 +52,7 @@ public class VirtualMachineTO { boolean rebootOnCrash; boolean enableHA; boolean limitCpuUse; + boolean enableDynamicallyScaleVm; String vncPassword; String vncAddr; Map params; @@ -102,6 +103,14 @@ public class VirtualMachineTO { this.id = id; } + public boolean isEnableDynamicallyScaleVm() { + return enableDynamicallyScaleVm; + } + + public void setEnableDynamicallyScaleVm(boolean enableDynamicallyScaleVm) { + this.enableDynamicallyScaleVm = enableDynamicallyScaleVm; + } + public String getName() { return name; } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java index 54aeef5a022..8e378093f3f 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java @@ -137,7 +137,7 @@ public class XenServer56FP1Resource extends XenServer56Resource { vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY; - if (isDmcEnabled(conn, host)) { + if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) { //scaling is allowed vmr.memoryStaticMin = mem_128m; //128MB //TODO: Remove hardcoded 8GB and assign proportionate to ServiceOffering and mem overcommit ratio diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 7c88aae5044..929d56bf10c 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -180,7 +180,8 @@ public enum Config { RouterTemplateLXC("Advanced", NetworkManager.class, String.class, "router.template.lxc", "SystemVM Template (LXC)", "Name of the default router template on LXC.", null, ConfigurationParameterScope.zone.toString()), RouterExtraPublicNics("Advanced", NetworkManager.class, Integer.class, "router.extra.public.nics", "2", "specify extra public nics used for virtual router(up to 5)", "0-5"), StartRetry("Advanced", AgentManager.class, Integer.class, "start.retry", "10", "Number of times to retry create and start commands", null), - ScaleRetry("Advanced", AgentManager.class, Integer.class, "scale.retry", "2", "Number of times to retry scaling up the vm", null), + EnableDynamicallyScaleVm("Advanced", ManagementServer.class, Boolean.class, "enable.dynamic.scale.vm", "false", "Enables/Diables dynamically scaling a vm", null, ConfigurationParameterScope.zone.toString()), + ScaleRetry("Advanced", ManagementServer.class, Integer.class, "scale.retry", "2", "Number of times to retry scaling up the vm", null), StopRetryInterval("Advanced", HighAvailabilityManager.class, Integer.class, "stop.retry.interval", "600", "Time in seconds between retries to stop or destroy a vm" , null), StorageCleanupInterval("Advanced", StorageManager.class, Integer.class, "storage.cleanup.interval", "86400", "The interval (in seconds) to wait before running the storage cleanup thread.", null), StorageCleanupEnabled("Advanced", StorageManager.class, Boolean.class, "storage.cleanup.enabled", "true", "Enables/disables the storage cleanup thread.", null), diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index ea4fcc1e5bf..d8945af9b8c 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -25,7 +25,9 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.configuration.Config; import com.cloud.offering.ServiceOffering; +import com.cloud.server.ConfigurationServer; import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.NicProfile; @@ -43,6 +45,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis @Inject NicDao _nicDao; @Inject VMInstanceDao _virtualMachineDao; @Inject NicSecondaryIpDao _nicSecIpDao; + @Inject ConfigurationServer _configServer; + protected HypervisorGuruBase() { super(); @@ -121,7 +125,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis // Workaround to make sure the TO has the UUID we need for Niciri integration VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId()); to.setUuid(vmInstance.getUuid()); - + + // + to.setEnableDynamicallyScaleVm(Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vm.getDataCenterId()))); + return to; } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 56578776b98..a734d44c800 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -32,6 +32,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.server.ConfigurationServer; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupVO; @@ -400,6 +401,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use AffinityGroupVMMapDao _affinityGroupVMMapDao; @Inject AffinityGroupDao _affinityGroupDao; + @Inject + ConfigurationServer _configServer; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -1141,6 +1144,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use boolean success = false; if(vmInstance.getState().equals(State.Running)){ int retry = _scaleRetry; + boolean enableDynamicallyScaleVm = Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vmInstance.getDataCenterId())); + if(!enableDynamicallyScaleVm){ + throw new PermissionDeniedException("Dynamically scaling virtual machines is disabled for this zone, please contact your admin"); + } + // Increment CPU and Memory count accordingly. if (newCpu > currentCpu) { _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index ec79237de5e..e081a252386 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1712,6 +1712,10 @@ update `cloud`.`vpc_gateways` set network_acl_id = 2; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'VpcManager', 'blacklisted.routes', NULL, 'Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'enable.dynamic.scale.vm', 'false', 'Enables/Diables dynamically scaling a vm'); + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'scale.retry', '2', 'Number of times to retry scaling up the vm'); + UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0; From 9905f656a5307c9d9b990ed988c2ea82b432231a Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 11:32:15 -0700 Subject: [PATCH 194/201] only check hypervisor type for security enabled advanced zone --- server/src/com/cloud/resource/ResourceManagerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 1e28d92896f..74bd6d04a3e 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -161,6 +161,7 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.dc.DataCenter.NetworkType; @Component @Local({ ResourceManager.class, ResourceService.class }) @@ -444,7 +445,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + cmd.getHypervisor() + " to a supported "); } - if (zone.isSecurityGroupEnabled()) { + if (zone.isSecurityGroupEnabled() && zone.getNetworkType().equals(NetworkType.Advanced)) { if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer && hypervisorType != HypervisorType.Simulator) { throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone"); From 6a7cc2021e627f68218ebb1c594a06dbcb148c51 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 13:45:07 -0700 Subject: [PATCH 195/201] when VR is rebooted, CloudStack will reapply all ips/rules to VR, this patch will reduce time the VR reboot takes - remove 1 s sleep in vmware - reduce the time arping takes --- patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh | 6 ++++-- utils/src/com/cloud/utils/ssh/SshHelper.java | 4 ---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh b/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh index f326fac9e54..d23ec00de5e 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh @@ -227,7 +227,8 @@ add_first_ip() { if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; fi add_routing $1 @@ -273,7 +274,8 @@ add_an_ip () { if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; fi add_routing $1 return $? diff --git a/utils/src/com/cloud/utils/ssh/SshHelper.java b/utils/src/com/cloud/utils/ssh/SshHelper.java index 6ee87ad722c..fb81e506ee5 100755 --- a/utils/src/com/cloud/utils/ssh/SshHelper.java +++ b/utils/src/com/cloud/utils/ssh/SshHelper.java @@ -146,10 +146,6 @@ public class SshHelper { } sess = conn.openSession(); - // There is a bug in Trilead library, wait a second before - // starting a shell and executing commands, from http://spci.st.ewi.tudelft.nl/chiron/xref/nl/tudelft/swerl/util/SSHConnection.html - Thread.sleep(1000); - sess.execCommand(command); InputStream stdout = sess.getStdout(); From 0b728f2e77c7ae69c8dcd4ddaba18559180454ae Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 13:51:22 -0700 Subject: [PATCH 196/201] remove unused file --- scripts/storage/qcow2/modifyvlan.sh | 269 ---------------------------- 1 file changed, 269 deletions(-) delete mode 100755 scripts/storage/qcow2/modifyvlan.sh diff --git a/scripts/storage/qcow2/modifyvlan.sh b/scripts/storage/qcow2/modifyvlan.sh deleted file mode 100755 index 5e26af0ba02..00000000000 --- a/scripts/storage/qcow2/modifyvlan.sh +++ /dev/null @@ -1,269 +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 -# 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. - - -# $Id: modifyvlan.sh 9132 2010-06-04 20:17:43Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/storage/qcow2/modifyvlan.sh $ -# modifyvlan.sh -- adds and deletes VLANs from a Routing Server -# set -x - -usage() { - printf "Usage: %s: -o -v -g \n" -} - -addVlan() { - local vlanId=$1 - - ifconfig bond1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - vconfig add bond1 $vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - fi - - # Make ifcfg-bond1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - touch /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "DEVICE=bond1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "ONBOOT=yes" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "BOOTPROTO=none" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "VLAN=yes" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "BRIDGE=xenbr1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - - # Try to add xenbr1.$vlanId over bond1.$vlanId, if it does not already exist - - ifconfig xenbr1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - brctl addbr xenbr1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl addif xenbr1.$vlanId bond1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - fi - - ifconfig xenbr1.$vlanId up - - if [ $? -gt 0 ] - then - return 1 - fi - - # Make ifcfg-xenbr1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - touch /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "TYPE=bridge" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "DEVICE=xenbr1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "ONBOOT=yes" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "BOOTPROTO=none" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - - return 0 -} - -deleteVlan() { - local vlanId=$1 - - # Try to remove xenbr1.$vlanId - ifconfig xenbr1.$vlanId down - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl delbr xenbr1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - # Remove ifcfg-xenbr1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - - # Try to remove bond1.$vlanId - - vconfig rem bond1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - # Remove ifcfg-bond1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - - return 0 - -} - -checkIfVlanExists() { - local vlanId=$1 - - if [ "$vlanId" == "untagged" ] - then - # This VLAN should always exist, since the bridge is xenbr1, which is created during vsetup - return 0 - fi - - ifconfig bond1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - return 1 - fi - - ifconfig xenbr1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - return 1 - fi - - if [ ! -f /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId ] - then - return 1 - fi - - if [ ! -f /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId ] - then - return 1 - fi - - return 0 -} - -arpingVlan() { - local vlanId=$1 - local vlanGateway=$2 - - # Change!!! - return 0 - - success=1 - for i in $(seq 1 3) - do - arping -I xenbr1.$vlanId $vlanGateway > /dev/null - - if [ $? -gt 0 ] - then - success=0 - break - fi - done - - return $success -} - -op= -vlanId= -vlanGateway= -option=$@ - -while getopts 'o:v:g:' OPTION -do - case $OPTION in - o) oflag=1 - op="$OPTARG" - ;; - v) vflag=1 - vlanId="$OPTARG" - ;; - g) gflag=1 - vlanGateway="$OPTARG" - ;; - ?) usage - exit 2 - ;; - esac -done - -# Check that all arguments were passed in -if [ "$oflag$vflag$gflag" != "111" ] -then - usage - exit 2 -fi - -if [ "$op" == "add" ] -then - # Check if the vlan already exists, and exit with success if it does - checkIfVlanExists $vlanId - - if [ $? -eq 0 ] - then - exit 0 - fi - - # Add the vlan - addVlan $vlanId - - # If the add fails then return failure - if [ $? -gt 0 ] - then - exit 1 - fi - - # Ping the vlan - arpingVlan $vlanId $vlanGateway - - # If the ping fails then delete the vlan and return failure. Else, return success. - if [ $? -gt 0 ] - then - deleteVlan $vlanId - exit 1 - else - exit 0 - fi -else - if [ "$op" == "delete" ] - then - # Delete the vlan - deleteVlan $vlanId - - # Always exit with success - exit 0 - fi -fi - - - - - - - - - - - - - From a91f04e759be7132ceda11ec5b3e1ff19d83c4e3 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 14:11:57 -0700 Subject: [PATCH 197/201] migrate volume in Vmware leaves a copy of this volume untracked in secondary storage, this patch removes the volume in secondary storag after volume migration --- .../manager/VmwareStorageManagerImpl.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index 9f1351e96f3..faadbacb0ef 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -491,6 +491,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { hyperHost, volumeId, new DatastoreMO(context, morDatastore), secondaryStorageURL, volumePath); + deleteVolumeDirOnSecondaryStorage(volumeId, secondaryStorageURL); } return new CopyVolumeAnswer(cmd, true, null, result.first(), result.second()); } catch (Throwable e) { @@ -1438,4 +1439,22 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { workingVM = hyperHost.findVmOnHyperHost(uniqueName); return workingVM; } + + + + private String deleteVolumeDirOnSecondaryStorage(long volumeId, String secStorageUrl) throws Exception { + String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl); + String volumeMountRoot = secondaryMountPoint + "/" + getVolumeRelativeDirInSecStroage(volumeId); + + return deleteDir(volumeMountRoot); + } + + private String deleteDir(String dir) { + synchronized(dir.intern()) { + Script command = new Script(false, "rm", _timeout, s_logger); + command.add("-rf"); + command.add(dir); + return command.execute(); + } + } } From 83c13fcf27a8635a743ba97c736c0fae1f66c9b6 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 29 May 2013 14:24:01 -0700 Subject: [PATCH 198/201] CLOUDSTACK-2614: Fix the permission of patchviasocket.pl It's non-executable now, which cause trouble on deb package. --- scripts/vm/hypervisor/kvm/patchviasocket.pl | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/vm/hypervisor/kvm/patchviasocket.pl diff --git a/scripts/vm/hypervisor/kvm/patchviasocket.pl b/scripts/vm/hypervisor/kvm/patchviasocket.pl old mode 100644 new mode 100755 From 3ae00f4b2fbbb305b783cff880ac92c3caf74871 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 14:44:47 -0700 Subject: [PATCH 199/201] update volume API needs to respect the account and domain --- server/src/com/cloud/storage/VolumeManagerImpl.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 4b654eb2253..aedb68e1316 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -358,6 +358,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throws ResourceAllocationException { Account caller = UserContext.current().getCaller(); long ownerId = cmd.getEntityOwnerId(); + Account owner = _accountDao.findById(ownerId); Long zoneId = cmd.getZoneId(); String volumeName = cmd.getVolumeName(); String url = cmd.getUrl(); @@ -367,7 +368,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { validateVolume(caller, ownerId, zoneId, volumeName, url, format); - VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName, + VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, cmd.getFormat()); VolumeInfo vol = this.volFactory.getVolume(volume.getId()); @@ -700,7 +701,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return UUID.randomUUID().toString(); } - private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, + private VolumeVO persistVolume(Account owner, Long zoneId, String volumeName, String url, String format) { Transaction txn = Transaction.currentTxn(); @@ -708,20 +709,17 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK); - Account owner = (caller.getId() == ownerId) ? caller : _accountMgr - .getActiveAccountById(ownerId); volume.setPoolId(null); volume.setDataCenterId(zoneId); volume.setPodId(null); - volume.setAccountId(ownerId); + volume.setAccountId(owner.getAccountId()); + volume.setDomainId(owner.getDomainId()); long diskOfferingId = _diskOfferingDao.findByUniqueName( "Cloud.com-Custom").getId(); volume.setDiskOfferingId(diskOfferingId); // volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date()); - volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner - .getDomainId()); volume = _volsDao.persist(volume); try { From a4d428434daa64221771597985cefa5f70741b96 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 15:10:49 -0700 Subject: [PATCH 200/201] Don't use volume name as snapshot name because volume name may incude space, \ and other special character, which cannot be part of path name in vmware after this commit, snapshot name is volumeUuid_timestring. --- .../com/cloud/storage/snapshot/SnapshotManagerImpl.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 26aae48ba38..92d80ee6cc8 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -1033,12 +1033,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, // Snapshot Name: VMInstancename + volumeName + timeString String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT); - VMInstanceVO vmInstance = _vmDao.findById(volume.getInstanceId()); - String vmDisplayName = "detached"; - if (vmInstance != null) { - vmDisplayName = vmInstance.getHostName(); - } - String snapshotName = vmDisplayName + "_" + volume.getName() + "_" + timeString; + String snapshotName = volume.getUuid() + "_" + timeString; // Create the Snapshot object and save it so we can return it to the // user From 56535a7a83f9871f97023e84f87bc9d65aa0f868 Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Wed, 29 May 2013 15:18:20 -0700 Subject: [PATCH 201/201] zero size of template/volume being registered causes infinite loop on SSVM, the fix is if the size is 0, return success without download --- .../com/cloud/storage/template/HttpTemplateDownloader.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java index 628ad64c0dc..c8aac27da8c 100644 --- a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java +++ b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java @@ -250,6 +250,13 @@ public class HttpTemplateDownloader implements TemplateDownloader { } } else { remoteSize2 = Long.parseLong(contentLengthHeader.getValue()); + if ( remoteSize2 == 0 ) { + status = TemplateDownloader.Status.DOWNLOAD_FINISHED; + String downloaded = "(download complete remote=" + remoteSize + "bytes)"; + errorString = "Downloaded " + totalBytes + " bytes " + downloaded; + downloadTime = 0; + return 0; + } } if (remoteSize == 0) {
    ').addClass('reorder').appendTo($thead); $('').addClass('reorder').appendTo($inputForm); $multi.find('.data-body').sortable({ - handle: '.action.moveDrag' + handle: '.action.moveDrag', + + update: function(event, ui) { + reorder.moveDrag.action({ + context: $.extend(true, {}, context, { + // Passes all rules, so that each index can be updated + multiRule: $multi.find('.data-item').map(function(index, item) { + return $(item).data('json-obj'); + }) + }), + response: { + success: function(args) { + } + } + }); + } }); } diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 5c2f0266d1b..d27e1fc44eb 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -30,7 +30,29 @@ reorder: { moveDrag: { action: function(args) { - args.response.success(); + $(args.context.multiRule.toArray().reverse()).map(function(index, rule) { + $.ajax({ + url: createURL('updateNetworkACLItem'), + data: { + id: rule.id, + number: index + 1 + }, + success: function(json) { + var pollTimer = setInterval(function() { + pollAsyncJobResult({ + _custom: { jobId: json.createnetworkaclresponse.jobid }, + complete: function() { + clearInterval(pollTimer); + }, + error: function(errorMsg) { + clearInterval(pollTimer); + cloudStack.dialog.notice(errorMsg); + } + }); + }, 1000); + } + }); + }); } } }, From f41d398cf75cee5e700d668252b4d52d5fe4f1a7 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Wed, 22 May 2013 16:05:03 -0700 Subject: [PATCH 078/201] Remote access vpn: method name change --- api/src/com/cloud/network/vpn/RemoteAccessVpnService.java | 2 +- .../api/command/user/vpn/DeleteRemoteAccessVpnCmd.java | 2 +- server/src/com/cloud/network/NetworkManagerImpl.java | 2 +- .../src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java | 4 ++-- server/src/com/cloud/user/AccountManagerImpl.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java index d637da638ac..b554719f188 100644 --- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java +++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java @@ -32,7 +32,7 @@ public interface RemoteAccessVpnService { RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, long networkId) throws NetworkRuleConflictException; - void destroyRemoteAccessVpn(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; + void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException; VpnUser addVpnUser(long vpnOwnerId, String userName, String password); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java index 5b1c5c6b4e6..06c25305a00 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java @@ -84,7 +84,7 @@ public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { @Override public void execute() throws ResourceUnavailableException { - _ravService.destroyRemoteAccessVpn(publicIpId, UserContext.current().getCaller()); + _ravService.destroyRemoteAccessVpnForIp(publicIpId, UserContext.current().getCaller()); } @Override diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 0f43b87685e..254510b15a9 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -3273,7 +3273,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // the code would be triggered s_logger.debug("Cleaning up remote access vpns as a part of public IP id=" + ipId + " release..."); try { - _vpnMgr.destroyRemoteAccessVpn(ipId, caller); + _vpnMgr.destroyRemoteAccessVpnForIp(ipId, caller); } catch (ResourceUnavailableException e) { s_logger.warn("Unable to destroy remote access vpn for ip id=" + ipId + " as a part of ip release", e); success = false; diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 062743b23af..9e7bb13b867 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -226,10 +226,10 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc } @Override @DB - public void destroyRemoteAccessVpn(long ipId, Account caller) throws ResourceUnavailableException { + public void destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException { RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId); if (vpn == null) { - s_logger.debug("vpn id=" + ipId + " does not exists "); + s_logger.debug("there are no Remote access vpns for public ip address id=" + ipId); return; } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index aac8d19eb0e..7421422d294 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -628,7 +628,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M try { for (RemoteAccessVpnVO vpn : remoteAccessVpns) { - _remoteAccessVpnMgr.destroyRemoteAccessVpn(vpn.getServerAddressId(), caller); + _remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller); } } catch (ResourceUnavailableException ex) { s_logger.warn("Failed to cleanup remote access vpn resources as a part of account id=" + accountId + " cleanup due to Exception: ", ex); From c52879b88c4cc418289e87927f5c10ddbfe62f82 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Wed, 22 May 2013 16:14:47 -0700 Subject: [PATCH 079/201] CLOUDSTACK-2627: disassociate ip address - assign return value of releaseIpAddress backend call to the result returned to the API caller --- .../api/command/user/address/DisassociateIPAddrCmd.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java index 8f78fe3a959..41691ea86d0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java @@ -76,9 +76,9 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { UserContext.current().setEventDetails("Ip Id: " + getIpAddressId()); boolean result = false; if (!isPortable(id)) { - _networkService.releaseIpAddress(getIpAddressId()); + result = _networkService.releaseIpAddress(getIpAddressId()); } else { - _networkService.releaseIpAddress(getIpAddressId()); + result = _networkService.releaseIpAddress(getIpAddressId()); } if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); From 0eb73e9dec3ac47bbce4349430598c7b8d640c59 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 16:28:09 -0700 Subject: [PATCH 080/201] Update VPC tier dashboard - Remove 'Port forwarders' -- Getting IPs by PF is not supported by API - Split Public + Internal LB into separate items - Use API response 'count' for count number, instead of array '.length' to fix issues with larger results --- ui/modules/vpc/vpc.js | 4 +- ui/scripts/vpc.js | 258 ++++++++++++++++++++++-------------------- 2 files changed, 135 insertions(+), 127 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index cc0273fcbb1..e313b8ab2b5 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -168,7 +168,7 @@ $total.find('span').html(dashboardItem.totalMultiLine); $total.addClass('multiline'); } else { - $total.find('span').html(dashboardItem.total); + $total.find('span').html(dashboardItem.total ? dashboardItem.total : 0); } $dashboardItem.append($total, $name); @@ -183,7 +183,7 @@ var $section = $('
    '); if ($.isFunction(section)) { - section = cloudStack.vpc.sections[id]() + section = cloudStack.vpc.sections[id](); } if (section.listView) { diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index d27e1fc44eb..2445adcd721 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -341,7 +341,7 @@ }, tierStaticNATs: function() { - return cloudStack.vpc.ipAddresses.listView(); + return cloudStack.vpc.staticNatIpAddresses.listView(); }, // Internal load balancers @@ -1185,7 +1185,7 @@ ipAddresses: { listView: function() { var listView = $.extend(true, {}, cloudStack.sections.network.sections.ipAddresses); - + listView.listView.fields = { ipaddress: listView.listView.fields.ipaddress, zonename: listView.listView.fields.zonename, @@ -1196,6 +1196,35 @@ return listView; } }, + staticNatIpAddresses: { + listView: function() { + var listView = $.extend(true, {}, cloudStack.sections.network.sections.ipAddresses); + + listView.listView.fields = { + ipaddress: listView.listView.fields.ipaddress, + zonename: listView.listView.fields.zonename, + associatednetworkname: { label: 'label.network.name' }, + state: listView.listView.fields.state + }; + + listView.listView.dataProvider = function(args) { + $.ajax({ + url: createURL('listPublicIpAddresses'), + data: { networkid: args.context.networks[0].id, isstaticnat: true }, + success: function(json) { + args.response.success({ + data: json.listpublicipaddressesresponse.publicipaddress + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }; + + return listView; + } + }, acl: { multiEdit: aclMultiEdit, @@ -3171,29 +3200,16 @@ async: true, success: function(json) { var networks = json.listnetworksresponse.network; - var loadBalancers, networkACLLists, publicIpAddresses, privateGateways, vpnGateways, portForwardingRules; + var networkACLLists, publicIpAddresses, privateGateways, vpnGateways; var error = false; - // Get load balancers - $.ajax({ - url: createURL('listLoadBalancers'), - data: { vpcid: args.context.vpc[0].id }, - success: function(json) { - loadBalancers = json.listloadbalancerssresponse.loadbalancer ? - json.listloadbalancerssresponse.loadbalancer : []; - }, - error: function(json) { - error = true; - } - }); - // Get network ACL lists $.ajax({ url: createURL('listNetworkACLLists'), data: { 'vpc_id': args.context.vpc[0].id }, + async: false, success: function(json) { - networkACLLists = json.listnetworkacllistsresponse.networkacllist ? - json.listnetworkacllistsresponse.networkacllist : []; + networkACLLists = json.listnetworkacllistsresponse; }, error: function(json) { error = true; @@ -3203,23 +3219,10 @@ // Get public IPs $.ajax({ url: createURL('listPublicIpAddresses'), + async: false, data: { 'vpcid': args.context.vpc[0].id }, success: function(json) { - publicIpAddresses = json.listpublicipaddressesresponse.publicipaddress ? - json.listpublicipaddressesresponse.publicipaddress : []; - }, - error: function(json) { - error = true; - } - }); - - // Get port forwarding rules - $.ajax({ - url: createURL('listPortForwardingRules'), - data: { 'vpcid': args.context.vpc[0].id }, - success: function(json) { - portForwardingRules = json.listportforwardingrulesresponse.portforwardingrule ? - json.listportforwardingrulesresponse.portforwardingrule : []; + publicIpAddresses = json.listpublicipaddressesresponse; }, error: function(json) { error = true; @@ -3229,10 +3232,10 @@ // Get private gateways $.ajax({ url: createURL('listPrivateGateways'), + async: false, data: { 'vpcid': args.context.vpc[0].id }, success: function(json) { - privateGateways = json.listprivategatewaysresponse.privategateway ? - json.listprivategatewaysresponse.privategateway : []; + privateGateways = json.listprivategatewaysresponse; }, error: function(json) { error = true; @@ -3242,106 +3245,111 @@ // Get VPN gateways $.ajax({ url: createURL('listVpnGateways'), + async: false, data: { 'vpcid': args.context.vpc[0].id }, success: function(json) { - vpnGateways = json.listvpngatewaysresponse.vpngateway ? - json.listvpngatewaysresponse.vpngateway : []; + vpnGateways = json.listvpngatewaysresponse; }, error: function(json) { error = true; } }); - var dataTimer = setInterval(function() { - var complete = loadBalancers && networkACLLists && publicIpAddresses && privateGateways && vpnGateways; - - if (complete) { - clearInterval(dataTimer); - - if(networks != null && networks.length > 0) { - for(var i = 0; i < networks.length; i++) { - $.ajax({ - url: createURL("listVirtualMachines"), - dataType: "json", - data: { - networkid: networks[i].id, - listAll: true - }, - async: false, - success: function(json) { - networks[i].virtualMachines = json.listvirtualmachinesresponse.virtualmachine; - } - }); - } + args.response.success({ + routerDashboard: [ + { + id: 'privateGateways', + name: 'Private gateways', + total: privateGateways.count + }, + { + id: 'publicIPs', + name: 'Public IP addresses', + total: publicIpAddresses.count + }, + { + id: 'siteToSiteVPNs', + name: 'Site-to-site VPNs', + total: vpnGateways.count + }, + { + id: 'networkACLLists', + name: 'Network ACL lists', + total: networkACLLists.count } - args.response.success({ - routerDashboard: [ - { - id: 'privateGateways', - name: 'Private gateways', - total: privateGateways.length - }, - { - id: 'publicIPs', - name: 'Public IP addresses', - total: publicIpAddresses.length - }, - { - id: 'siteToSiteVPNs', - name: 'Site-to-site VPNs', - total: vpnGateways.length - }, - { - id: 'networkACLLists', - name: 'Network ACL lists', - total: networkACLLists.length - } - ], - tiers: $(networks).map(function(index, tier) { - var internalLoadBalancers = $.grep(loadBalancers, function(lb) { - return lb.networkid == tier.id; - }); - - return $.extend(tier, { - _dashboardItems: [ - { - id: 'tierLoadBalancers', - name: 'Load balancers', - totalMultiLine: internalLoadBalancers.length + ' Internal
    0 Public' - }, - { - id: 'tierPortForwarders', - name: 'Port forwarders', - total: $.grep(publicIpAddresses, function(ip) { - return $.grep( - portForwardingRules, - function(pf) { - return pf.ipaddressid == ip.id; - } - ).length ? true : false; - }).length - }, - { - id: 'tierStaticNATs', - name: 'Static NATs', - total: $.grep(publicIpAddresses, function(ip) { - return ip.associatednetworkid == tier.id && ip.isstaticnat; - }).length - }, - { - id: 'tierVMs', - name: 'Virtual Machines', - total: $.isArray(tier.virtualMachines) ? tier.virtualMachines.length : 0 - } - ] - }); - }) + ], + tiers: $(networks).map(function(index, tier) { + var internalLoadBalancers, publicLoadBalancers, virtualMachines, staticNatIps; + + // Get internal load balancers + $.ajax({ + url: createURL('listLoadBalancers'), + async: false, + data: { networkid: tier.id }, + success: function(json) { + internalLoadBalancers = json.listloadbalancerssresponse; + }, + error: function(json) { + error = true; + } }); - } else if (error) { - clearInterval(dataTimer); - cloudStack.dialog.notice({ message: 'Error loading dashboard data.' }); - } - }, 500); + + // Get VMs + $.ajax({ + url: createURL('listVirtualMachines'), + async: false, + data: { networkid: tier.id }, + success: function(json) { + virtualMachines = json.listvirtualmachinesresponse; + }, + error: function(json) { + error = true; + } + }); + + // Get static NAT IPs + $.ajax({ + url: createURL('listPublicIpAddresses'), + async: false, + data: { networkid: tier.id, isstaticnat: true }, + success: function(json) { + staticNatIps = json.listpublicipaddressesresponse; + }, + error: function(json) { + error = true; + } + }); + + return $.extend(tier, { + _dashboardItems: [ + { + id: 'tierLoadBalancers', + name: 'Internal LB', + total: internalLoadBalancers.count + }, + { + id: 'tierLoadBalancers', + name: 'Public LB', + total: 0 + }, + { + id: 'tierStaticNATs', + name: 'Static NATs', + total: staticNatIps.count + }, + { + id: 'tierVMs', + name: 'Virtual Machines', + total: virtualMachines.count + } + ] + }); + }) + }); + + if (error) { + cloudStack.dialog.notice({ message: 'Error loading dashboard data.' }); + } } }); } From 9071456596df15e3570c882c18143c93bbc38eee Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Wed, 22 May 2013 16:32:20 -0700 Subject: [PATCH 081/201] Split 'internal LB' / 'public LB' into separate list views, intead of subsections --- ui/scripts/vpc.js | 651 +++++++++++++++++++++++----------------------- 1 file changed, 320 insertions(+), 331 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 2445adcd721..fa0ed926551 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -345,349 +345,338 @@ }, // Internal load balancers - tierLoadBalancers: { - listView: true, - sectionSelect: { - label: 'Select LB type' - }, - sections: { - internalLoadBalancers: { - type: 'select', - title: 'Internal LB', - listView: { - id: 'internalLoadBalancers', - fields: { - name: { label: 'label.name' }, - sourceipaddress: { label: 'Source IP Address' } + internalLoadBalancers: { + title: 'Internal LB', + listView: { + id: 'internalLoadBalancers', + fields: { + name: { label: 'label.name' }, + sourceipaddress: { label: 'Source IP Address' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + networkid: args.context.networks[0].id }, - dataProvider: function(args) { - $.ajax({ - url: createURL('listLoadBalancers'), - data: { - networkid: args.context.networks[0].id - }, - success: function(json) { - var items = json.listloadbalancerssresponse.loadbalancer; - args.response.success({ data: items }); - - } - }); - }, - actions: { - add: { - label: 'Add Internal LB', - createForm: { - title: 'Add Internal LB', - fields: { - name: { label: 'label.name', validation: { required: true } }, - description: { label: 'label.description', validation: { required: false } }, - sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, - sourceport: { label: 'sourceport', validation: { required: true } }, - instanceport: { label: 'instanceport', validation: { required: true } }, - algorithm: { - label: 'label.algorithm', - validation: { required: true }, - select: function(args) { - args.response.success({ - data: [ - { id: 'source', description: 'source' }, - { id: 'roundrobin', description: 'roundrobin' }, - { id: 'leastconn', description: 'leastconn' } - ] - }); - } - } + success: function(json) { + var items = json.listloadbalancerssresponse.loadbalancer; + args.response.success({ data: items }); + + } + }); + }, + actions: { + add: { + label: 'Add Internal LB', + createForm: { + title: 'Add Internal LB', + fields: { + name: { label: 'label.name', validation: { required: true } }, + description: { label: 'label.description', validation: { required: false } }, + sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, + sourceport: { label: 'sourceport', validation: { required: true } }, + instanceport: { label: 'instanceport', validation: { required: true } }, + algorithm: { + label: 'label.algorithm', + validation: { required: true }, + select: function(args) { + args.response.success({ + data: [ + { id: 'source', description: 'source' }, + { id: 'roundrobin', description: 'roundrobin' }, + { id: 'leastconn', description: 'leastconn' } + ] + }); } - }, - messages: { - notification: function(args) { - return 'Add Internal LB'; - } - }, - action: function(args) { - var data = { - name: args.data.name, - sourceport: args.data.sourceport, - instanceport: args.data.instanceport, - algorithm: args.data.algorithm, - networkid: args.context.networks[0].id, - sourceipaddressnetworkid: args.context.networks[0].id, - scheme: 'Internal' - }; - if(args.data.description != null && args.data.description.length > 0){ - $.extend(data, { - description: args.data.description - }); - } - if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ - $.extend(data, { - sourceipaddress: args.data.sourceipaddress - }); - } - $.ajax({ - url: createURL('createLoadBalancer'), - data: data, - success: function(json){ - var jid = json.createloadbalancerresponse.jobid; - args.response.success( - {_custom: - {jobId: jid, - getUpdatedItem: function(json) { - return json.queryasyncjobresultresponse.jobresult.loadbalancer; - } - } - } - ); - } - }); - - args.response.success(); - }, - notification: { - poll: pollAsyncJobResult - } + } } }, - - detailView: { - name: 'Internal Lb details', - actions: { - assignVm: { - label: 'Assign VMs to LB', - messages: { - notification: function(args) { return 'Assign VM to internal LB rule'; } - }, - listView: $.extend(true, {}, cloudStack.sections.instances.listView, { - type: 'checkbox', - filters: false, - dataProvider: function(args) { - $.ajax({ - url: createURL('listVirtualMachines'), - data: { - networkid: args.context.networks[0].id, - listAll: true - }, - success: function(json) { - var instances = json.listvirtualmachinesresponse.virtualmachine; - - // Pre-select existing instances in LB rule - $(instances).map(function(index, instance) { - instance._isSelected = $.grep( - args.context.internalLoadBalancers[0].loadbalancerinstance, - - function(lbInstance) { - return lbInstance.id == instance.id; - } - ).length ? true : false; - }); - - args.response.success({ - data: instances - }); - } - }); - } - }), - action: function(args) { - var vms = args.context.instances; - var array1 = []; - for(var i = 0; i < vms.length; i++) { - array1.push(vms[i].id); - } - var virtualmachineids = array1.join(','); - - $.ajax({ - url: createURL('assignToLoadBalancerRule'), - data: { - id: args.context.internalLoadBalancers[0].id, - virtualmachineids: virtualmachineids - }, - dataType: 'json', - async: true, - success: function(data) { - var jid = data.assigntoloadbalancerruleresponse.jobid; - args.response.success({ - _custom: { jobId: jid } - }); - } - }); - }, - notification: { - poll: pollAsyncJobResult - } - } - }, - tabs: { - details: { - title: 'label.details', - fields: [ - { - name: { label: 'label.name' } - }, - { - id: { label: 'label.id' } - } - ], - dataProvider: function(args) { - $.ajax({ - url: createURL('listLoadBalancers'), - data: { - id: args.context.internalLoadBalancers[0].id - }, - success: function(json) { - var item = json.listloadbalancerssresponse.loadbalancer[0]; - args.response.success({ data: item }); - } - }); - } - }, - rules: { - title: 'label.rules', - multiple: true, - fields: [ - { - sourceport: { label: 'Source Port' }, - instanceport: { label: 'Instance Port' } - } - ], - dataProvider: function(args) { - $.ajax({ - url: createURL('listLoadBalancers'), - data: { - id: args.context.internalLoadBalancers[0].id - }, - success: function(json) { - var item = json.listloadbalancerssresponse.loadbalancer[0]; - args.response.success({ data: item.loadbalancerrule }); - } - }); - } - } , - assignedVms: { - title: 'Assigned VMs', - multiple: true, - fields: [ - { - name: { label: 'label.name' }, - ipaddress: { label: 'label.ip.address' } - } - ], - dataProvider: function(args) { - $.ajax({ - url: createURL('listLoadBalancers'), - data: { - id: args.context.internalLoadBalancers[0].id - }, - success: function(json) { - var item = json.listloadbalancerssresponse.loadbalancer[0]; - args.response.success({ data: item.loadbalancerinstance }); - } - }); - } - } + messages: { + notification: function(args) { + return 'Add Internal LB'; + } + }, + action: function(args) { + var data = { + name: args.data.name, + sourceport: args.data.sourceport, + instanceport: args.data.instanceport, + algorithm: args.data.algorithm, + networkid: args.context.networks[0].id, + sourceipaddressnetworkid: args.context.networks[0].id, + scheme: 'Internal' + }; + if(args.data.description != null && args.data.description.length > 0){ + $.extend(data, { + description: args.data.description + }); + } + if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ + $.extend(data, { + sourceipaddress: args.data.sourceipaddress + }); } - } + $.ajax({ + url: createURL('createLoadBalancer'), + data: data, + success: function(json){ + var jid = json.createloadbalancerresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancer; + } + } + } + ); + } + }); + + args.response.success(); + }, + notification: { + poll: pollAsyncJobResult + } } }, - - publicLoadBalancers: { - type: 'select', - title: 'Public LB', - listView: { - id: 'publicLoadBalancers', - fields: { - ipaddress: { label: 'label.ip.address' }, - type: { label: 'label.type' } - }, - dataProvider: function(args) { - args.response.success({ - data: [ - { ipaddress: '10.3.2.1', type: 'Internal' }, - { ipaddress: '10.3.2.3', type: 'Internal' }, - { ipaddress: '10.232.1.4', type: 'Public' } - ] - }); - }, - actions: { - add: { - label: 'Add Public LB', - createForm: { - title: 'Add Public LB', - fields: { - name: { label: 'label.name', validation: { required: true } }, - description: { label: 'label.description', validation: { required: false } }, - sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, - sourceport: { label: 'sourceport', validation: { required: true } }, - instanceport: { label: 'instanceport', validation: { required: true } }, - algorithm: { - label: 'label.algorithm', - validation: { required: true }, - select: function(args) { - args.response.success({ - data: [ - { id: 'source', description: 'source' }, - { id: 'roundrobin', description: 'roundrobin' }, - { id: 'leastconn', description: 'leastconn' } - ] - }); - } - } - } - }, - messages: { - notification: function(args) { - return 'Add Public LB'; - } - }, - action: function(args) { - var data = { - name: args.data.name, - sourceport: args.data.sourceport, - instanceport: args.data.instanceport, - algorithm: args.data.algorithm, - networkid: args.context.networks[0].id, - sourceipaddressnetworkid: args.context.networks[0].id, - scheme: 'Public' - }; - if(args.data.description != null && args.data.description.length > 0){ - $.extend(data, { - description: args.data.description - }); - } - if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ - $.extend(data, { - sourceipaddress: args.data.sourceipaddress - }); - } + + detailView: { + name: 'Internal Lb details', + actions: { + assignVm: { + label: 'Assign VMs to LB', + messages: { + notification: function(args) { return 'Assign VM to internal LB rule'; } + }, + listView: $.extend(true, {}, cloudStack.sections.instances.listView, { + type: 'checkbox', + filters: false, + dataProvider: function(args) { $.ajax({ - url: createURL('createLoadBalancer'), - data: data, - success: function(json){ - var jid = json.createloadbalancerresponse.jobid; - args.response.success( - {_custom: - {jobId: jid, - getUpdatedItem: function(json) { - return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + url: createURL('listVirtualMachines'), + data: { + networkid: args.context.networks[0].id, + listAll: true + }, + success: function(json) { + var instances = json.listvirtualmachinesresponse.virtualmachine; + + // Pre-select existing instances in LB rule + $(instances).map(function(index, instance) { + instance._isSelected = $.grep( + args.context.internalLoadBalancers[0].loadbalancerinstance, + + function(lbInstance) { + return lbInstance.id == instance.id; } - } - } - ); + ).length ? true : false; + }); + + args.response.success({ + data: instances + }); } }); - - args.response.success(); - }, - notification: { - poll: function(args) { - args.complete({ - data: { - ipaddress: '10.0.3.2', - type: 'Internal' - } + } + }), + action: function(args) { + var vms = args.context.instances; + var array1 = []; + for(var i = 0; i < vms.length; i++) { + array1.push(vms[i].id); + } + var virtualmachineids = array1.join(','); + + $.ajax({ + url: createURL('assignToLoadBalancerRule'), + data: { + id: args.context.internalLoadBalancers[0].id, + virtualmachineids: virtualmachineids + }, + dataType: 'json', + async: true, + success: function(data) { + var jid = data.assigntoloadbalancerruleresponse.jobid; + args.response.success({ + _custom: { jobId: jid } }); } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + id: { label: 'label.id' } } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item }); + } + }); + } + }, + rules: { + title: 'label.rules', + multiple: true, + fields: [ + { + sourceport: { label: 'Source Port' }, + instanceport: { label: 'Instance Port' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item.loadbalancerrule }); + } + }); + } + } , + assignedVms: { + title: 'Assigned VMs', + multiple: true, + fields: [ + { + name: { label: 'label.name' }, + ipaddress: { label: 'label.ip.address' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item.loadbalancerinstance }); + } + }); + } + } + } + } + } + }, + publicLoadBalancers: { + title: 'Public LB', + listView: { + id: 'publicLoadBalancers', + fields: { + ipaddress: { label: 'label.ip.address' }, + type: { label: 'label.type' } + }, + dataProvider: function(args) { + args.response.success({ + data: [ + { ipaddress: '10.3.2.1', type: 'Internal' }, + { ipaddress: '10.3.2.3', type: 'Internal' }, + { ipaddress: '10.232.1.4', type: 'Public' } + ] + }); + }, + actions: { + add: { + label: 'Add Public LB', + createForm: { + title: 'Add Public LB', + fields: { + name: { label: 'label.name', validation: { required: true } }, + description: { label: 'label.description', validation: { required: false } }, + sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, + sourceport: { label: 'sourceport', validation: { required: true } }, + instanceport: { label: 'instanceport', validation: { required: true } }, + algorithm: { + label: 'label.algorithm', + validation: { required: true }, + select: function(args) { + args.response.success({ + data: [ + { id: 'source', description: 'source' }, + { id: 'roundrobin', description: 'roundrobin' }, + { id: 'leastconn', description: 'leastconn' } + ] + }); + } + } + } + }, + messages: { + notification: function(args) { + return 'Add Public LB'; + } + }, + action: function(args) { + var data = { + name: args.data.name, + sourceport: args.data.sourceport, + instanceport: args.data.instanceport, + algorithm: args.data.algorithm, + networkid: args.context.networks[0].id, + sourceipaddressnetworkid: args.context.networks[0].id, + scheme: 'Public' + }; + if(args.data.description != null && args.data.description.length > 0){ + $.extend(data, { + description: args.data.description + }); + } + if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ + $.extend(data, { + sourceipaddress: args.data.sourceipaddress + }); + } + $.ajax({ + url: createURL('createLoadBalancer'), + data: data, + success: function(json){ + var jid = json.createloadbalancerresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + } + } + } + ); + } + }); + + args.response.success(); + }, + notification: { + poll: function(args) { + args.complete({ + data: { + ipaddress: '10.0.3.2', + type: 'Internal' + } + }); } } } @@ -3323,12 +3312,12 @@ return $.extend(tier, { _dashboardItems: [ { - id: 'tierLoadBalancers', + id: 'internalLoadBalancers', name: 'Internal LB', total: internalLoadBalancers.count }, { - id: 'tierLoadBalancers', + id: 'publicLoadBalancers', name: 'Public LB', total: 0 }, From a69101dceb535af2d6c6382b83d26f14d4ef03bf Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Wed, 22 May 2013 16:17:14 -0700 Subject: [PATCH 082/201] - To check if a host is in avoid set, DPM should check the zones/pods/cluster/hosts in teh avoid list - not just the hosts in avoid list. --- .../deploy/DeploymentPlanningManagerImpl.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index c86d5e1a1b2..795b526c403 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -380,7 +380,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (planner instanceof DeploymentClusterPlanner) { - ExcludeList PlannerAvoidInput = new ExcludeList(avoids.getDataCentersToAvoid(), + ExcludeList plannerAvoidInput = new ExcludeList(avoids.getDataCentersToAvoid(), avoids.getPodsToAvoid(), avoids.getClustersToAvoid(), avoids.getHostsToAvoid(), avoids.getPoolsToAvoid()); @@ -388,19 +388,19 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (clusterList != null && !clusterList.isEmpty()) { // planner refactoring. call allocators to list hosts - ExcludeList PlannerAvoidOutput = new ExcludeList(avoids.getDataCentersToAvoid(), + ExcludeList plannerAvoidOutput = new ExcludeList(avoids.getDataCentersToAvoid(), avoids.getPodsToAvoid(), avoids.getClustersToAvoid(), avoids.getHostsToAvoid(), avoids.getPoolsToAvoid()); - resetAvoidSet(PlannerAvoidOutput, PlannerAvoidInput); + resetAvoidSet(plannerAvoidOutput, plannerAvoidInput); dest = checkClustersforDestination(clusterList, vmProfile, plan, avoids, dc, - getPlannerUsage(planner), PlannerAvoidOutput); + getPlannerUsage(planner), plannerAvoidOutput); if (dest != null) { return dest; } // reset the avoid input to the planners - resetAvoidSet(avoids, PlannerAvoidOutput); + resetAvoidSet(avoids, plannerAvoidOutput); } else { return null; @@ -815,12 +815,8 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy // remove any hosts/pools that the planners might have added // to get the list of hosts/pools that Allocators flagged as 'avoid' - if (allocatorAvoidOutput.getHostsToAvoid() != null && plannerAvoidOutput.getHostsToAvoid() != null) { - allocatorAvoidOutput.getHostsToAvoid().removeAll(plannerAvoidOutput.getHostsToAvoid()); - } - if (allocatorAvoidOutput.getPoolsToAvoid() != null && plannerAvoidOutput.getPoolsToAvoid() != null) { - allocatorAvoidOutput.getPoolsToAvoid().removeAll(plannerAvoidOutput.getPoolsToAvoid()); - } + + resetAvoidSet(allocatorAvoidOutput, plannerAvoidOutput); // if all hosts or all pools in the cluster are in avoid set after this // pass, then put the cluster in avoid set. @@ -829,8 +825,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy List allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(Host.Type.Routing, clusterVO.getId(), clusterVO.getPodId(), clusterVO.getDataCenterId(), null); for (HostVO host : allhostsInCluster) { - if (allocatorAvoidOutput.getHostsToAvoid() == null - || !allocatorAvoidOutput.getHostsToAvoid().contains(host.getId())) { + if (!allocatorAvoidOutput.shouldAvoid(host)) { // there's some host in the cluster that is not yet in avoid set avoidAllHosts = false; } @@ -839,8 +834,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy List allPoolsInCluster = _storagePoolDao.findPoolsByTags(clusterVO.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null); for (StoragePoolVO pool : allPoolsInCluster) { - if (allocatorAvoidOutput.getPoolsToAvoid() == null - || !allocatorAvoidOutput.getPoolsToAvoid().contains(pool.getId())) { + if (!allocatorAvoidOutput.shouldAvoid(pool)) { // there's some pool in the cluster that is not yet in avoid set avoidAllPools = false; } From 4786420986b60955ca8f084f24b69f9d07153ab5 Mon Sep 17 00:00:00 2001 From: Mice Xia Date: Thu, 23 May 2013 09:54:46 +0800 Subject: [PATCH 083/201] [Automation] fix CLOUDSTACK-2546 Failed to add second NIC to vm in KVM environment --- test/integration/smoke/test_nic.py | 51 +++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/test/integration/smoke/test_nic.py b/test/integration/smoke/test_nic.py index bae6dfda15d..8e8d3407dfb 100644 --- a/test/integration/smoke/test_nic.py +++ b/test/integration/smoke/test_nic.py @@ -79,11 +79,35 @@ class Services: "PortForwarding": 'VirtualRouter', }, }, + "network_offering_shared": { + "name": 'Test Network offering shared', + "displaytext": 'Test Network offering Shared', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "traffictype": 'GUEST', + "specifyVlan" : "True", + "specifyIpRanges" : "True", + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter', + }, + }, "network": { "name": "Test Network", "displaytext": "Test Network", "acltype": "Account", }, + "network2": { + "name": "Test Network Shared", + "displaytext": "Test Network Shared", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype": "Account", + }, # ISO settings for Attach/Detach ISO tests "iso": { "displaytext": "Test ISO", @@ -176,6 +200,14 @@ class TestDeployVM(cloudstackTestCase): self.network_offering.update(self.apiclient, state='Enabled') # Enable Network offering self.services["network"]["networkoffering"] = self.network_offering.id + self.network_offering_shared = NetworkOffering.create( + self.apiclient, + self.services["network_offering_shared"], + ) + self.cleanup.insert(0, self.network_offering_shared) + self.network_offering_shared.update(self.apiclient, state='Enabled') # Enable Network offering + self.services["network2"]["networkoffering"] = self.network_offering_shared.id + ################ ### Test Network self.test_network = Network.create( @@ -185,6 +217,14 @@ class TestDeployVM(cloudstackTestCase): self.account.domainid, ) self.cleanup.insert(0, self.test_network) + self.test_network2 = Network.create( + self.apiclient, + self.services["network2"], + self.account.name, + self.account.domainid, + zoneid=self.services["network"]["zoneid"] + ) + self.cleanup.insert(0, self.test_network2) except Exception as ex: self.debug("Exception during NIC test SETUP!: " + str(ex)) self.assertEqual(True, False, "Exception during NIC test SETUP!: " + str(ex)) @@ -201,10 +241,10 @@ class TestDeployVM(cloudstackTestCase): accountid=self.account.name, domainid=self.account.domainid, serviceofferingid=self.service_offering.id, - mode=self.services['mode'] + mode=self.services['mode'], + networkids=[self.test_network.id] ) self.cleanup.insert(0, self.virtual_machine) - list_vm_response = list_virtual_machines( self.apiclient, id=self.virtual_machine.id @@ -256,7 +296,7 @@ class TestDeployVM(cloudstackTestCase): existing_nic_id = vm_response.nic[0].id # 1. add a nic - add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network.id) + add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network2.id) time.sleep(5) # now go get the vm list? @@ -308,8 +348,9 @@ class TestDeployVM(cloudstackTestCase): sawException = True self.assertEqual(sawException, True, "Make sure we cannot delete the default NIC") - - self.virtual_machine.remove_nic(self.apiclient, existing_nic_id) + self.virtual_machine.update_default_nic(self.apiclient, existing_nic_id) + time.sleep(5) + self.virtual_machine.remove_nic(self.apiclient, new_nic_id) time.sleep(5) list_vm_response = list_virtual_machines( From 795fd803da3eadee0fae1a13d0e97ae57b239657 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Wed, 22 May 2013 23:12:30 -0600 Subject: [PATCH 084/201] Summary: KVM - double migration can fail Detail: Undefine VM after migration. Lingering domain definitions cause migrations back to the original host to fail, since domain already exists. BUG-ID: CLOUDSTACK-2640 Bugfix-for: 4.1.0,4.2.0 Signed-off-by: Marcus Sorensen 1369285950 -0600 --- .../hypervisor/kvm/resource/LibvirtComputingResource.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index b31fb5dfbe5..09038559ab9 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -2728,6 +2728,9 @@ ServerResource { } finally { try { if (dm != null) { + if (dm.isPersistent() == 1) { + dm.undefine(); + } dm.free(); } if (dconn != null) { From fce59b8fc42412f87ccbda5cf4f53e1465935070 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Wed, 22 May 2013 23:30:49 -0600 Subject: [PATCH 085/201] Summary: Code cleanup for KVM - look up domains by name rather than coversion Detail: We do two strange things, #1, when a vm is created, we create the uuid for the domain by converting the name into a uuid, then subsequently, any time we look for a domain, we convert its name to a uuid and domainLookupByUUID. This is an unnecessary obfuscation, so instead we just do a domainLookupByName. As a bonus, we are now setting the domain's uuid to be the cloudstack uuid. It is no longer used anywhere, but will be less confusing to admins. This shouldn't affect upgrades, since we can always lookup existing VMs by name. Signed-off-by: Marcus Sorensen 1369287049 -0600 --- .../resource/LibvirtComputingResource.java | 45 +++++++------------ .../LibvirtComputingResourceTest.java | 4 +- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 09038559ab9..1e20d75a6a0 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -2619,8 +2619,7 @@ ServerResource { Domain vms = null; while (retry-- > 0) { try { - vms = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + vms = conn.domainLookupByName(vmName); State s = convertToState(vms.getInfo().state); return s; } catch (final LibvirtException e) { @@ -2712,8 +2711,7 @@ ServerResource { try { conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName()); ifaces = getInterfaces(conn, vmName); - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); dconn = new Connect("qemu+tcp://" + cmd.getDestinationIp() + "/system"); /* @@ -3162,8 +3160,7 @@ ServerResource { protected LibvirtVMDef createVMFromSpec(VirtualMachineTO vmTO) { LibvirtVMDef vm = new LibvirtVMDef(); vm.setDomainName(vmTO.getName()); - vm.setDomUUID(UUID.nameUUIDFromBytes(vmTO.getName().getBytes()) - .toString()); + vm.setDomUUID(vmTO.getUuid()); vm.setDomDescription(vmTO.getOs()); GuestDef guest = new GuestDef(); @@ -3587,8 +3584,7 @@ ServerResource { KVMStoragePool attachingPool = attachingDisk.getPool(); try { if (!attach) { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); String xml = dm.getXMLDesc(0); parser.parseDomainXML(xml); @@ -3637,9 +3633,7 @@ ServerResource { InternalErrorException { Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes((vmName - .getBytes()))); - + dm = conn.domainLookupByName(vmName); if (attach) { s_logger.debug("Attaching device: " + xml); dm.attachDevice(xml); @@ -3870,8 +3864,7 @@ ServerResource { for (; i < 5; i++) { try { Connect conn = LibvirtConnection.getConnectionByVmName(vm); - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vm - .getBytes())); + dm = conn.domainLookupByName(vm); DomainInfo.DomainState vps = dm.getInfo().state; if (vps != null && vps != DomainInfo.DomainState.VIR_DOMAIN_SHUTOFF @@ -4008,8 +4001,7 @@ ServerResource { for (int i = 0; i < vms.length; i++) { try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vms[i] - .getBytes())); + dm = conn.domainLookupByName(vms[i]); DomainInfo.DomainState ps = dm.getInfo().state; final State state = convertToState(ps); @@ -4114,8 +4106,7 @@ ServerResource { Domain dm = null; String msg = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String vmDef = dm.getXMLDesc(0); s_logger.debug(vmDef); msg = stopVM(conn, vmName); @@ -4157,8 +4148,7 @@ ServerResource { /* Retry 3 times, to make sure we can get the vm's status */ for (int i = 0; i < 3; i++) { try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); state = dm.getInfo().state; break; } catch (LibvirtException e) { @@ -4194,8 +4184,7 @@ ServerResource { protected String stopVM(Connect conn, String vmName, boolean force) { Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); int persist = dm.isPersistent(); if (force) { if (dm.isActive() == 1) { @@ -4282,8 +4271,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String xmlDesc = dm.getXMLDesc(0); parser.parseDomainXML(xmlDesc); return parser.getVncPort(); @@ -4328,8 +4316,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String xmlDesc = dm.getXMLDesc(0); parser.parseDomainXML(xmlDesc); return parser.getDescription(); @@ -4427,15 +4414,14 @@ ServerResource { private Domain getDomain(Connect conn, String vmName) throws LibvirtException { return conn - .domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes())); + .domainLookupByName(vmName); } protected List getInterfaces(Connect conn, String vmName) { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); parser.parseDomainXML(dm.getXMLDesc(0)); return parser.getInterfaces(); @@ -4457,8 +4443,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); parser.parseDomainXML(dm.getXMLDesc(0)); return parser.getDisks(); diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 39e36d65c65..0bafd073f68 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -60,6 +60,7 @@ public class LibvirtComputingResourceTest { LibvirtComputingResource lcr = new LibvirtComputingResource(); VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, speed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); LibvirtVMDef vm = lcr.createVMFromSpec(to); vm.setHvsType(_hyperVisorType); @@ -135,6 +136,7 @@ public class LibvirtComputingResourceTest { LibvirtComputingResource lcr = new LibvirtComputingResource(); VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); LibvirtVMDef vm = lcr.createVMFromSpec(to); vm.setHvsType(_hyperVisorType); @@ -181,4 +183,4 @@ public class LibvirtComputingResourceTest { assertEquals(vmStr, vm.toString()); } -} \ No newline at end of file +} From 4fdd0261fe82b3a3fa7c8360ebb49429f0c36d7c Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Thu, 23 May 2013 14:56:32 +0530 Subject: [PATCH 086/201] port forwarding issues with the listNics API response parameter --- ui/scripts/network.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 6b310ce0e83..3eef1367e97 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -50,7 +50,7 @@ nicId: nic.id }, success: function(json) { - var nic = json.listnics.nic[0]; + var nic = json.listnicsresponse.nic[0]; var ips = nic.secondaryip ? nic.secondaryip : []; var ipSelection = []; From 4e7f87681c8ac15aee56e39693d7a328ccf97f7f Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Thu, 23 May 2013 16:07:26 +0530 Subject: [PATCH 087/201] CLOUDSTACK-1396: uuid field is NULL in hypervisore_capability table for Vmware ESXI 5.1 Adding uuid at the time of inserting new entry in hypervisor_capabilities table --- setup/db/db/schema-410to420.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 7b5e9cb5f29..ea7a18df0ff 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -25,8 +25,8 @@ SET foreign_key_checks = 0; ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `max_hosts_per_cluster` int unsigned DEFAULT NULL COMMENT 'Max. hosts in cluster supported by hypervisor'; ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `storage_motion_supported` int(1) unsigned DEFAULT 0 COMMENT 'Is storage motion supported'; UPDATE `cloud`.`hypervisor_capabilities` SET `max_hosts_per_cluster`=32 WHERE `hypervisor_type`='VMware'; -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES ('XenServer', '6.1.0', 50, 1, 13, 1); -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES ('VMware', '5.1', 128, 0, 32); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES (UUID(), 'XenServer', '6.1.0', 50, 1, 13, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES (UUID(), 'VMware', '5.1', 128, 0, 32); DELETE FROM `cloud`.`configuration` where name='vmware.percluster.host.max'; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xen.nics.max', '7', 'Maximum allowed nics for Vms created on Xen'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.apiserver.address', 'http://localhost:8081', 'Specify the address at which the Midonet API server can be contacted (if using Midonet)'); @@ -348,7 +348,7 @@ ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `uuid` varchar(40) UNIQUE; -- START: support for LXC -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('LXC', 'default', 50, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'LXC', 'default', 50, 1); ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `lxc_network_label` varchar(255) DEFAULT 'cloudbr0' COMMENT 'The network name label of the physical device dedicated to this traffic on a LXC host'; UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC' WHERE name='hypervisor.list'; From 80a3c0535e0a8ad3edba3713a61d063a176191d8 Mon Sep 17 00:00:00 2001 From: Devdeep Singh Date: Thu, 23 May 2013 16:50:33 +0530 Subject: [PATCH 088/201] CLOUDSTACK-2643: Implicit dedication planner isn't listed in non oss builds. The entry for implicit planner was missing in nonoss component context xml. Added it there. --- client/tomcatconf/nonossComponentContext.xml.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index 1b6ee6eb089..6fa9d38baa4 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -251,7 +251,7 @@ - + From cc492305cead9307b9959fa696e11f0fad415c0a Mon Sep 17 00:00:00 2001 From: Chip Childers Date: Thu, 23 May 2013 17:50:15 +0100 Subject: [PATCH 089/201] CLOUDSTACK-2612: Correcting missing db qualifiers in schema-302to40.sql Signed-off-by: Chip Childers --- setup/db/db/schema-302to40.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup/db/db/schema-302to40.sql b/setup/db/db/schema-302to40.sql index f17f067c6ef..7fa73483db6 100644 --- a/setup/db/db/schema-302to40.sql +++ b/setup/db/db/schema-302to40.sql @@ -134,7 +134,7 @@ ALTER TABLE `cloud`.`account` ADD COLUMN `default_zone_id` bigint unsigned; ALTER TABLE `cloud`.`account` ADD CONSTRAINT `fk_account__default_zone_id` FOREIGN KEY `fk_account__default_zone_id`(`default_zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE; -DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); +DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM `cloud`.`storage_pool` WHERE removed IS NOT NULL); DROP TABLE IF EXISTS `cloud`.`cluster_vsm_map`; DROP TABLE IF EXISTS `cloud`.`virtual_supervisor_module`; @@ -179,14 +179,14 @@ CREATE TABLE `cloud`.`port_profile` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); +DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM `cloud`.`storage_pool` WHERE removed IS NOT NULL); ALTER TABLE `cloud`.`service_offering` MODIFY `nw_rate` smallint(5) unsigned DEFAULT '200' COMMENT 'network rate throttle mbits/s'; -- 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`; +ALTER TABLE `cloud`.`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` ( @@ -232,9 +232,9 @@ CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( -- Remove the unique constraint on physical_network_id, provider_name from physical_network_service_providers -- Because the name of this contraint is not set we need this roundabout way -- The key is also used by the foreign key constraint so drop and recreate that one -ALTER TABLE physical_network_service_providers DROP FOREIGN KEY fk_pnetwork_service_providers__physical_network_id; +ALTER TABLE `cloud`.`physical_network_service_providers` DROP FOREIGN KEY fk_pnetwork_service_providers__physical_network_id; -SET @constraintname = (select CONCAT(CONCAT('DROP INDEX ', A.CONSTRAINT_NAME), ' ON physical_network_service_providers' ) +SET @constraintname = (select CONCAT(CONCAT('DROP INDEX ', A.CONSTRAINT_NAME), ' ON cloud.physical_network_service_providers' ) from information_schema.key_column_usage A JOIN information_schema.key_column_usage B ON B.table_name = 'physical_network_service_providers' AND B.COLUMN_NAME = 'provider_name' AND A.COLUMN_NAME ='physical_network_id' AND B.CONSTRAINT_NAME=A.CONSTRAINT_NAME where A.table_name = 'physical_network_service_providers' LIMIT 1); @@ -243,7 +243,7 @@ PREPARE stmt1 FROM @constraintname; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; -AlTER TABLE physical_network_service_providers ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; +AlTER TABLE `cloud`.`physical_network_service_providers` ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; UPDATE `cloud`.`configuration` SET description='In second, timeout for creating volume from snapshot' WHERE name='create.volume.from.snapshot.wait'; ALTER TABLE `cloud`.`data_center` ADD COLUMN `is_local_storage_enabled` tinyint NOT NULL DEFAULT 0 COMMENT 'Is local storage offering enabled for this data center; 1: enabled, 0: not'; From 623a26e469ca7354a7dbe6b8954276985e289687 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 23 May 2013 21:59:32 +0530 Subject: [PATCH 090/201] CLOUDSTACK-2587: netscaler_pod_ref DB upgrade is missing from 3.0.2 to 4.x added missing schema as part of 4.0 to 4.1 upgrade --- setup/db/db/schema-40to410.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index b7b1c7a91dd..381a4cea612 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -1639,3 +1639,15 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Usage', 'DEFAULT', 'manageme INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (163, UUID(), 10, 'Ubuntu 12.04 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (164, UUID(), 10, 'Ubuntu 12.04 (64-bit)'); + +DROP TABLE IF EXISTS `cloud`.`netscaler_pod_ref`; +CREATE TABLE `cloud`.`netscaler_pod_ref` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `external_load_balancer_device_id` bigint unsigned NOT NULL COMMENT 'id of external load balancer device', + `pod_id` bigint unsigned NOT NULL COMMENT 'pod id', + PRIMARY KEY (`id`), + CONSTRAINT `fk_ns_pod_ref__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_ns_pod_ref__device_id` FOREIGN KEY (`external_load_balancer_device_id`) REFERENCES `external_load_balancer_devices`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'eip.use.multiple.netscalers' , 'false', 'Should be set to true, if there will be multiple NetScaler devices providing EIP service in a zone'); From d515602873b7cd0810ce602b274e5b4e57bebd0b Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Thu, 23 May 2013 10:39:32 -0700 Subject: [PATCH 091/201] CLOUDSTACK UI - VPC - site-to-site VPN - VPN connection - fix a JS error "elems is undefined" when clicking Create VPN Connection. --- ui/scripts/vpc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index fa0ed926551..923c51039b6 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -2060,7 +2060,7 @@ listAll: true }, success: function(json) { - var items = json.listvpncustomergatewaysresponse.vpncustomergateway; + var items = json.listvpncustomergatewaysresponse.vpncustomergateway ? json.listvpncustomergatewaysresponse.vpncustomergateway: []; args.response.success({ data: $.map(items, function(item) { return { From bc7d7e64c0f4cbcf3960b2387caa7cfff88e9c77 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Thu, 23 May 2013 11:39:27 -0700 Subject: [PATCH 092/201] CLOUDSTACK-747: UI - VPC tier - implement count of Public LB IP. --- ui/scripts/vpc.js | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 923c51039b6..ae3001af2f1 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -582,10 +582,10 @@ } } }, - publicLoadBalancers: { + publicLbIps: { title: 'Public LB', listView: { - id: 'publicLoadBalancers', + id: 'publicLbIps', fields: { ipaddress: { label: 'label.ip.address' }, type: { label: 'label.type' } @@ -3268,7 +3268,7 @@ } ], tiers: $(networks).map(function(index, tier) { - var internalLoadBalancers, publicLoadBalancers, virtualMachines, staticNatIps; + var internalLoadBalancers, publicLbIps, virtualMachines, staticNatIps; // Get internal load balancers $.ajax({ @@ -3283,19 +3283,19 @@ } }); - // Get VMs + // Get Public LB IPs $.ajax({ - url: createURL('listVirtualMachines'), + url: createURL('listPublicIpAddresses'), async: false, - data: { networkid: tier.id }, + data: { networkid: tier.id, forloadbalancing: true }, success: function(json) { - virtualMachines = json.listvirtualmachinesresponse; + publicLbIps = json.listpublicipaddressesresponse; }, error: function(json) { error = true; } - }); - + }); + // Get static NAT IPs $.ajax({ url: createURL('listPublicIpAddresses'), @@ -3309,6 +3309,19 @@ } }); + // Get VMs + $.ajax({ + url: createURL('listVirtualMachines'), + async: false, + data: { networkid: tier.id }, + success: function(json) { + virtualMachines = json.listvirtualmachinesresponse; + }, + error: function(json) { + error = true; + } + }); + return $.extend(tier, { _dashboardItems: [ { @@ -3317,9 +3330,9 @@ total: internalLoadBalancers.count }, { - id: 'publicLoadBalancers', - name: 'Public LB', - total: 0 + id: 'publicLbIps', + name: 'Public LB IP', + total: publicLbIps.count }, { id: 'tierStaticNATs', From a292bfbfcd8823d28c2f0f4b706be0d1ed9256f2 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Thu, 23 May 2013 11:53:25 -0700 Subject: [PATCH 093/201] CLOUDSTACK-747: UI - VPC tier - Public LB IP - populate listView of Public LB IP. --- ui/scripts/vpc.js | 119 +++++++++++----------------------------------- 1 file changed, 28 insertions(+), 91 deletions(-) diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index ae3001af2f1..2183aba55fd 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -587,100 +587,37 @@ listView: { id: 'publicLbIps', fields: { - ipaddress: { label: 'label.ip.address' }, - type: { label: 'label.type' } - }, - dataProvider: function(args) { - args.response.success({ - data: [ - { ipaddress: '10.3.2.1', type: 'Internal' }, - { ipaddress: '10.3.2.3', type: 'Internal' }, - { ipaddress: '10.232.1.4', type: 'Public' } - ] - }); - }, - actions: { - add: { - label: 'Add Public LB', - createForm: { - title: 'Add Public LB', - fields: { - name: { label: 'label.name', validation: { required: true } }, - description: { label: 'label.description', validation: { required: false } }, - sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, - sourceport: { label: 'sourceport', validation: { required: true } }, - instanceport: { label: 'instanceport', validation: { required: true } }, - algorithm: { - label: 'label.algorithm', - validation: { required: true }, - select: function(args) { - args.response.success({ - data: [ - { id: 'source', description: 'source' }, - { id: 'roundrobin', description: 'roundrobin' }, - { id: 'leastconn', description: 'leastconn' } - ] - }); - } - } - } - }, - messages: { - notification: function(args) { - return 'Add Public LB'; - } - }, - action: function(args) { - var data = { - name: args.data.name, - sourceport: args.data.sourceport, - instanceport: args.data.instanceport, - algorithm: args.data.algorithm, - networkid: args.context.networks[0].id, - sourceipaddressnetworkid: args.context.networks[0].id, - scheme: 'Public' - }; - if(args.data.description != null && args.data.description.length > 0){ - $.extend(data, { - description: args.data.description - }); - } - if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ - $.extend(data, { - sourceipaddress: args.data.sourceipaddress - }); - } - $.ajax({ - url: createURL('createLoadBalancer'), - data: data, - success: function(json){ - var jid = json.createloadbalancerresponse.jobid; - args.response.success( - {_custom: - {jobId: jid, - getUpdatedItem: function(json) { - return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; - } - } - } - ); - } - }); - - args.response.success(); - }, - notification: { - poll: function(args) { - args.complete({ - data: { - ipaddress: '10.0.3.2', - type: 'Internal' - } - }); + ipaddress: { + label: 'label.ips', + converter: function(text, item) { + if (item.issourcenat) { + return text + ' [' + _l('label.source.nat') + ']'; } + + return text; } + }, + zonename: { label: 'label.zone' }, + virtualmachinedisplayname: { label: 'label.vm.name' }, + state: { + converter: function(str) { + // For localization + return str; + }, + label: 'label.state', indicator: { 'Allocated': 'on', 'Released': 'off' } } - } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listPublicIpAddresses'), + async: false, + data: { networkid: args.context.networks[0].id, forloadbalancing: true }, + success: function(json) { + var items = json.listpublicipaddressesresponse; + args.response.success({ data: items }); + } + }); + } } }, From 1201d623a7091517a1e26bc4b82c5daeea3c155f Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Thu, 23 May 2013 16:58:12 +0200 Subject: [PATCH 094/201] CLOUDSTACK-862 Updated documentation with the new features available in the Nicira NVP plugin. --- docs/en-US/CloudStack_Nicira_NVP_Guide.xml | 1 + docs/en-US/images/nvp-add-controller.png | Bin 0 -> 35928 bytes docs/en-US/images/nvp-enable-provider.png | Bin 0 -> 32158 bytes docs/en-US/images/nvp-network-offering.png | Bin 0 -> 104060 bytes .../en-US/images/nvp-physical-network-stt.png | Bin 0 -> 27317 bytes docs/en-US/images/nvp-vpc-offering-edit.png | Bin 0 -> 29279 bytes docs/en-US/plugin-niciranvp-about.xml | 2 +- .../plugin-niciranvp-devicemanagement.xml | 32 ++--- docs/en-US/plugin-niciranvp-features.xml | 67 +++++++-- docs/en-US/plugin-niciranvp-introduction.xml | 5 +- .../plugin-niciranvp-networkofferings.xml | 131 ++++++++++++++++++ docs/en-US/plugin-niciranvp-physicalnet.xml | 37 +++++ docs/en-US/plugin-niciranvp-preparations.xml | 11 +- docs/en-US/plugin-niciranvp-provider.xml | 28 ++-- docs/en-US/plugin-niciranvp-revisions.xml | 14 ++ docs/en-US/plugin-niciranvp-tables.xml | 105 ++++++++++---- docs/en-US/plugin-niciranvp-usage.xml | 11 +- ...nvp-guide.xml => plugin-niciranvp-vpc.xml} | 19 ++- docs/en-US/plugin-niciranvp-vpcfeatures.xml | 28 ++++ .../plugin-niciranvp-vpcnetworkoffering.xml | 81 +++++++++++ docs/en-US/plugin-niciranvp-vpcoffering.xml | 38 +++++ 21 files changed, 516 insertions(+), 94 deletions(-) create mode 100644 docs/en-US/images/nvp-add-controller.png create mode 100644 docs/en-US/images/nvp-enable-provider.png create mode 100644 docs/en-US/images/nvp-network-offering.png create mode 100644 docs/en-US/images/nvp-physical-network-stt.png create mode 100644 docs/en-US/images/nvp-vpc-offering-edit.png create mode 100644 docs/en-US/plugin-niciranvp-networkofferings.xml create mode 100644 docs/en-US/plugin-niciranvp-physicalnet.xml rename docs/en-US/{plugin-niciranvp-guide.xml => plugin-niciranvp-vpc.xml} (65%) create mode 100644 docs/en-US/plugin-niciranvp-vpcfeatures.xml create mode 100644 docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml create mode 100644 docs/en-US/plugin-niciranvp-vpcoffering.xml diff --git a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml index 7f156d5dc09..5431fc1cb43 100644 --- a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml +++ b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml @@ -48,6 +48,7 @@ + diff --git a/docs/en-US/images/nvp-add-controller.png b/docs/en-US/images/nvp-add-controller.png new file mode 100644 index 0000000000000000000000000000000000000000..e02d31f0a37edca722c3a97312b2e5103ec723c5 GIT binary patch literal 35928 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
    A!%81Nb!39{uO}ejDzKkr?+by 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 HfLfH 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 Lm2kLVVfI$`EgD)y^rNc}_fYo_?A~iSqM_k* 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 SWzM%`3Hs7>~{WmF09u4W)}Jw z5*HW}c{>>0? z*8!-eyE-9QZ0>8~b^v~=;P7lk~M>i+i z+_@`K-_WSW>0)JiHe3U>h8pky5>b+7zmzWViJ$9!+%7;TP9(% z;zLj?N5Irl%LT4bji&O5z|>)1jOTd=7waL0r@S|gt@0aY&7jdTJ;ycgUpOz#Fge?Q31->V_dv}YuzU>^dYs@@fHwr+DD zHsBAZOtURfap!#?ZlC65CX%~XeJ_}F1WRrssVEqw!3*F2gQ?C(kFET^Oy9kEyNmDf8@2!vMKh7GEEMNZI0 zx_G*W#1M8YV}Bpol;PqxKx7E^+NPXFoa%3}kEQmN2ExUJNu0daV7Q`6kOABTnspT8Ny4g$0`+)uLiE~`fbr*$E%;KeV{ zMdtM-&hlf01j+Nvd#+WGvMSm-0(QdnPKHgou!a-B0t1zRY2i*dKn_1?|B;O)n}8%O z(U+)2q4;fRMVjYeVwQaLVl+V#l4HBvk==5cHacz4&IusI=qH^Llg;#fr)8Dq>~uMs zZo8n)l*46uUyEPs5#FRY?5Mz!aiZNZtYi|*4@w^?aL@tY!{$WAL6c43SBc|sH(nz0 zDPUv_?vAye-?c~+6D*%M9vI@f8w+B$wPeRV?{8HX&6kEH15V7vZkDY28kL$sm~_mJYBzinz?=|dyYuB){8Q#t(b#GM;<>ZuKU~j z%qP#}sgFQM!t~^1&*$^M`p_wsyga_9qPG{8)~1h4h`rbfL-tvvGM+af;-+tOjqU~q z;2|1&9-3k=hYeT?rx>1@6zL&_iWIzK$xgxt&$|sQ+1P1Ig(mh-LVIkX?Apyj^JMaK z$d9ozBadACGM2Ztl!o!EtEUJ6WgZe3!9s*pbki8IeA*#E*w#Vpt_r6K(~c!jfM-8{L~e(KWuhTu*?1=r9B(JDeHJyMaA z?!ozI(IKxFGa@UD<$Z$=^*ies^FJU)qHhLeLJ9ab>RFzacuibIIO>E4G92ZsDeD{= zh7&8R!K`F)s)PEdseuBAo#1-H^~`gbf+%pG*PM4WKWqNF>Pm0> znc0D_96^N1v)t+I0hNvu(>Wn~o3uUmwd|^yXfRl3$ikZzEGH;k;~!%0+Ycx2TD`LY z-;gTF$8zQEKj)AVUROe&MXh7YbWdxC6pp(=$s)f>cF4j*Ndt%mX=?2jpB>zM6{v$$ zsVLTlnNfg(EPljR%NFig&HfTZ3yrs}V;PIWKabKr__q$b4w!-4sY@Ysg?!6{Z(yGU zEMlM$)w(NG7C}^_KA1H4PY3C`rkK>0WRwPq(_~lKsi`;)qglY$3pp4;oSfsnCd#K9 zj%@xSlZu<`U~CDs3d%=iXAC@y_v;Pq`GlZP$&Uxgr@?n?SbESv&^cfYa`ckfxI4tcqEoG`pXfdd-iXb zF&!h+8-27QYUS#n@J1}mG2*sdfV2~Ad(Iv6Rk+U?EG1o zwqfFF$>{#88_PT2AQK-mzDHl^tdrczGmM$uWeMU$Wh ztGmAH?-?dYoZnx}`J95BkMvCvA`i$nBE5;lRkBYU$jhbLQO7 zwg02xS*qDu$_s!rW}LB()9O~4G_{Y}a;F##aBp4FBU)lY2pc>oZd@*5+)mMw(?3Z4 z@$EAC9O+T)0(P)weJ;$PzC47&=DmR`x}$Za?lu7n;@sP8#=jc?-|aSXr46Jg=B_D z^rBPH2nDkZx4T;>gm1B?gMld;4Hr4-6Rj0rpOprLVHMcr?=j{ zhr9J$pPJv^%h1~NMS531)e)$}q<~-Gx z%c${q^2D9m#Axj&yMJk|82&KdG{lpdy4GRY#`S)p_dK`C;_B>-HHEtO>degHcf|$u z^vKRks7r)`&JPR;W*cbj4!7&-6WzA>ul4T417hB+V?u$k$sJX@Un=JpfLa3nom&3* zO_H-u(OewvZ@lD*+`ZFM#jgAKYVt-9rZ+8e;a2q=3SK*(ehuBDSG;Wc>|f}))mV_q6Q*dtbPfB#oXt z5brkKOb?&T@~N00&~6DU6KYbC;L%xF+>S1XQv*3jDD#i_W+RT*=`in@1qFOPh-Q2K ztW1m)MsqZ|Sg$5id)UO6ecYjluSLn0uyqS1WstNCFg#dir~NJH@x*)7P|wZdpM8?GN0adSe(Y_Z z+2Le3yFU$^5%N33i+@V@FD!!x@Z`tA`Ui?o{OH%L@)Hk`>=20Xe3q(>ZI{{xuJ3JOA%qf500Q10nq<5+Wn?&t|B8qsQpCge8x{Hb%QL zaCGQPn*|JbO?@LebprQ&oVOK@<`789pHaNh8+B{;g*gZov|#V4Q&^p za<3SDNS}{IKLLn+yLYVg07Jsf@Qyu&HesdyH!I%@Lev?tc?AFGTiG$XhjXnrW%k3D zdIvPx7#`aH&zP@@K<~J>4_l&Ebn|+Jp0A_e!dm6M@H;#FK!RRr+9!bJ(0g6pR=T}D zftAQ*{VX$JBOl-A-we%~NtZO$J+U{BaJkWYURkGjC=A{jX-@U`=Gb>IBs#M44W6Lg`On4RjqwDKYip#1 zb(a$DKi54Gv<}5rTQ7r2)6wnDkp!OIrv98T^#3gWF(pt4vBydE z_u~_9*d5vrG#PGZVgF3|`A;Hz=}icVr4He2nVcN`X8aC%UA=Ss@YJkGZ<}$VSiSt= z1MI(9AuJaCC8%1HmB%Qka}_&S`=gGk6p-A!jKObNE~#7x?;mtNJ`HA?y`>KOTE=Cc zf*U1J01HO~soMfiRYTeiK> z=E$)0**YrExYH-<^n1p~$Ioj7r05@CH8^hGI^1#lohz2Kiu+B$)Ys6A-CnYC?+#olwW3z%=)iR6e_>Fiw;~8#&pU;H@mTC<&LQEys*-< z0$?k9AM#wW5HAjqQ*d1imiKfF3*oSlg75$t_dxehQ#+al(a89P)IJS)*mvs&SDm-Q zQyIyA9q2)sG2UM!(sxAv$GN>5QV?Z^`~IsDEI_#oftTAk02AhNSwPR@{XRAK0z%5!e(O zr?+RbV)YQxQzce}nDct?T$))stSjhr!>ItsJggdCOXr0>@=GW5bp+e)e)i)q7|p0Q zbb`78n5`at7|}^GKfge^bZa8x#&M2qp#yhh@%+WcV^ygcUjNmu&}Uy5w`<(h`N92f z1TTp7P0ED5J<3bG+)J3P1=EkORW2QcY96;UTo7%)Nh%{7fojsSohP%Lou_g#-;f$z z$=(PX{F0hUZ+9j0m35JAJX>nqb5AOp=d9623A+g^psj|Jox&d&v|8_$f%KZ>`{J|J zP?FQBkKL?6qPq3;8m~8OfkdxYFZk zZsr7zh7ODL-i^LSJw(T`XeFH-mRp3osSLr62*afz+Zw9~C&wo7V|Po~@=HD!M(WuM zDhT+t>Z%p{B_>}IofcMi9ko=M!C>|Gg_!^pV>L~+C!3gHV)hvaFV`1p7TWwr9Nbeo ztD~^9i0)A@4JyRM(#}1u@TUXm?`0NBO*QG7nc~uCxcD=g8d4>#qRT*1+Z@)a>(k!; zK3~`4m!a}2wYu{>Lj-{B3w$ts)Xim&kgl)ePVTDp{F)y}?v6hIZd@W$27LZJU*6m| zWbkzx4VU5(7pbq*-s)u!v&=db@Gd2=6<96z_*4H{j87xqH$Ex5v{89XJv}Df4Vci5 zio{u&mGgbsox;5$^h{0v+!4~s%9En4U44ZB+W8~rMOW3L$@q<~$mItS9~>NJJ?8e3 zr7$sRfD^@V3p&1m!iCr&DUB_^T%YbUifEhHEBb7OVP`FM@WFU^4tU9Idzvx{oMY)) zXE&XnG%j2A3^|2QpJ#zX{v%q3!47TIUn2UVsk zPl6A!S6MsY1;1RZ|IsEhIhwNE zn_Jq;bb+)*`OUNzTXag^MeF{Rd(u*!9ndjPJnx*CsTjvXzn;-r8uY%rZij{)Nb1WW zZMu2^1e_)XVBt{QlUU;c4n|+=a!VHtzXb7lZRT zbmC@h3{-T8a(8WKZA@nue1z+vr*y<^Dc>^6(jzav=qWuPfh8X7p7XFsm93cFi+s5~ zJ0Dub$L&&Ez8#hStd5wURPLj8(E(gba5pz|P;SAihn%4hvC?J8Lvi}0=smOim!zmk z)UQn6l7@F$JmmyNP0XG`Fj=jm?bJ8-*S=v|%kefYzMl|Bp1Lo6L2kg}oZ6;b{8$-J$#Q_ZzL zt%S>o@y9&Rv7N^TWU47$y$Z!1#EG_U zp4Tldn`PL+46~ieWWmsRdzZk_Nb+_BuXiF{ya z-+Tc{cwPQ{%&LFdsN0y47i{M^6LAdC) zr$1SSv5~_~;+&AONxmzh2`L?0KI{@}v}B4#&j$!k&rA#5jIo~yW*qIvYt@6`7hR8+ zE8_Ie6q%^a;*F>eMF3o( zqw{lb*(eMfa%C0g>KT$JlGG)Doi~ zG(eoZ4$RHjvKQ{#8jHsLAG!QRKp*p4pdKEf`{J)=kRb>mS6(^or!}LzHY@?R=igmh z#%eIZ&-JYab7fK9q?6DvIU-c7UNw+yvdsF3^I1}YEzzQ4 zCQkH_TTixdP1niMrR=?M<%a6F?3;m03|UJ+uZth3a#g#LGk&I2cH=^_#e^rvDK=<* zfWL`{NG_w)6j)MIGc4%gXt;MX`xdvLu%uw9B(64fyG!M4*~=o;Px0tO4!SO%%czju z+ZIXI9Wm_wd_5hXcI-FK^dGrTap0nt3U?R78}AECW4gALNrItrX_K5C`~BBi#-bVZ zMMy^v7Y+HFCif$kno4Wq`%&!7_nR{g%ysNvw!n3v`N1u=Y<@g6^2pG%8DVHt0Xav}&o=FZK+L-R<4;} zcJy?U+;m)FlG|_s@bezr<3LZk>y0vPMpn9&3Uyz@D`g^bYT!c#APyPdi|rSJVg#P) zh_6*Pa{OhEbKXLuH*lf-b~tCchn=j)`Q7}LPDxBYHWzy@nkiv`zTFZ z2W&3Uk%dQA1Z<{xVcj-DsKdkDQ~6;?Jwwm$9v@lri;`OD$iXeBU6G&%^ElKq4<&>V zBkM+gCeh7WW;9mR-G@;Dn7FrCzhT!cf;miJQWrb0pJLMpgRSIF8|^K> zcf}39dp2f53uM*%;<(B7-f_T&*Y5BK0O+K_ryAx}WHbdUd%q(vO?!(8k{u0vJu!vw ze**pIIbp;rkEh+&Q5ex?c+0++xJ|sLVt!TIyQHR}I|79W-{IIp7tzGDFX;ID{r z`znmHWP91!NaSwaQv$WO8q}z*Y0w-lJ}UPSNg&77wk?Fq2!&s6hly5^4cg^=UA9|L z$<2>SQ(x7qcT-GBNy+XG63kv6bgA!t&;B%=FOdHS#?ZCrIaI>#vx1$0>x#-RL)Dnw z@U}q6A~kN`e6f?xcOzG$xRm*=g|=^??rqlmm74ld=4QvaXTl}uJ z?-Xs8Zf`wMCeC?1xoS{8Q1}Fpff1~yW-{ckRb%=1@ngX*F=J#Z^hqY-BJC+sgKGNpDo$9yAzbjsjG?HiObs|{UO%wBetXI0%Wv4hWF-U_4a0F)VQr4x&~96rs{$vh&us}&ES$&E;1L0h zRmheqe>G50B-##5&w>$>#+RwiWkX^-oibsn25(S6$kn>>{ z`H`)nZRe~)jcj76E`7LKX+k&S_DI4mlgU67-^`->E4H&<3GDy{@zyUJw73BV%#1O5vkqS$M3+J^gjH~|YP(N*P>-||`k=p_OLK#LdqEtn2L1TRu zm=U__DBnvajGHbU1FY4($0xiC@mY$on%B$6=poT;c8FxwRArS`FOSTj)$%G>%`DSp zYjQd1VHUPt9){R9Z5EToiwNM}#XPLDJ9#|=REu^cRS`}bW(zyv2T1y0zoO~*_DS9X zfDv4d-bIOFyYsbaY2QquzO6-Bt+YHwj0xQTWpdZ}GUe>JZ}#!=c4H)+w^Hld#Nq>K zaEbEfWJK^&a&3zf&ef+bIG5(IA4bv$N5V|0d(u}db7}9n@~jI=#q8X!J{*xJ(Exw$ z8|RK`#yjv^sAipHdwZB>TPf#i^3}*Zc+B!j&AK4IGVF2XcZXW$MS-_!s;n_wsoce@ z&n<$CvYAu`;=vAL!b-E+hhN4}d)00-FtZF5YoX;Rr z&9+=|HMQut=%O1Dwdw_ib+Q&?&DArGHaLN1lXGmm?E+&lk6ICNOr$BDu`j|eV#nES zoU*}mnybtyTc!*)d{)*|c)ZJ#-+TW5wDO%{O>JGbDhQ}_l_CMu2q;xSAkq;8>AfSN z2BnzLM7k6O1p-K~iu5joBE3lsMS&;?hTeN9p#=DLJm>nJd%pMF^XKMQo@ei8@44n& zd#yF*oMSMJtGG%?y>b(r?X|aV@?4)iw7BS=hF!(pWTymOjo@=wv4~H-pxEU`65rML z2t9M>DDj3_Q7RJ`jnDX_jG4ek)ao_7c>GjrKm0J#@5#tmZDXwd;iQYR7qBCcEJhhL z-zhdb=zCltF2{Fu2=9cP_(=L-eBW``LpU-bB>2XB`9#RfBE^NOkW!`0vx);aAxbt* zC@Fa}x7=~&HQl2niXDgc?w#b!x-w<%e0v+CULj@cG5&CacX4qiE8uXyI)i5?^U-BH zGp&ME2jiLEqo9#ok=T;FVF#F8er2s+1XukoyOgJD@enf79;TNIwbzrrnLqGgXSwK+ zBGQ9iK~Ej|9C4!ni3;`0RY(I`fFnpsR|Z{AM@(b+G6y zmMnVE0pYXF(!pZcx71)d5Xnr<>&um?w4nWoQ#P552G0IE3deB@guVwqJHdVu4}*jQ zz=(hhBka3%%D&k53F!^u0pPx-`t)?Yqx@>V>y~6YQ7)wca%W%Qm`hRMpB^`Oq2$O; z2c?XB+j`+v%Oy-M>`tLke8ZLr7j56iV6~+^VKC`-(YmhQoH(>VPYXu*@(vED8RAT=p&oJ%^q{Hsd}d zrQa6f)auA#zD6&cOfMkqc7gyXEI(YwTucaa2-vd-FzMKJ@XLuWC>G;{1!g+1X3FVU zpK2Nk$wA!?0p`AVZRrO%E&QYuIy7tS1;&M5(mCh=@468$@jfB+q?LURdZ1a)_ zv|d=R7HOQicCk+AHHt?+wksn-ir;aYW$0I@Cmdu9|psjYuqTBpWXM8;#o#FE? z@_|a6*PGbHa(^$vG;;v>ML>q^YjR1KFXlnPX56vR=BSSZrb*gF4kz{qymUa|)hjZ9 zjMR{&yj(av%}#Ia>~xW6*9VvJw`~RuX}9?n2x*1+K6_&31&a+w3 zg8|c_tR*{!+HNbKZ-K8q1>uoH1x67UxlD$%b4;x5w$9!2oBTjWW^8KcCH*w&36RBO z44&hjynSCk-%BG!g2Pb-9>u~~2_%cBKQRyJ3rWCAI)#_KU1n;gmm1Ip#mciQ1N0zr z>gpi5p_8t7-6!c&*c0I7!*p0f+G#9=_Mg~j@haYdUrpd~5TXMOW;gOg+`O~d($tLW zaUq#0_VPl{RAJ*v;bEfprxWMN6I>3Gw5+h(mv~$-{J1VEJS|A}63CPDT3Jjt2jnf) zSaj;vr_B6oy*N5hwUc(hqg@DWfG)eG-lkt_q|gjriz+orGQrwhKG6iz)`vv97WCy!d^2mHe9chej&tNRVR;zI~iqCt1C-tGDFl zK$OR+efVEr*7wv?lbRIhE4UPhcoe^AcGcpsC(-f zd#eft?qpbO(!@uYa7vce+6eNq7o_~5me*a&XcYU6XGU=&^Uc{#0%P+(R;<$BF~R6< z@wx0Osgm;~9v+<((dA9g7or+)O>#anBgZ7Ov*{(>=5B;mk1d;itWTO{);mWI_`0b) zf>axEGwM$3h{PH_XxAk7gJ`&Ta_6+;m8yP^A9suK5jVJ{yWVo!`jH8NNLAn23Qf6@ zCb|aYiNze*6_uJ@$%@ynShJ6}(d+N->09sIc7duTVC@gm9LA&!lJG0>HSG*8e)-Op z{VW#gctnpOvm5++^PQsE7}Eiv%j<=486E1KiTT%*y~md5LEi*#sk}D@2l8l)3W3%i z=Fr^`?HX0fO$7xsVOI3vR z`&#Z*vf{WLqtC%6RRpq?@5ro#cP4sNUH@*IA-`u z7jLOHIzPK!NaqL^RaO5~w!Kt$83|NvpR;Y;c=pN~#p8M->xz89mts}%7Hh{rp^G_~ ziTVe85kCsj`YPPn-YQf?)fG;W80qf3KiF)v$H3u)hjV$oGb)u5Tr8sTuYKR-Ko4`{ z%@_Nl?L@9!By3M$JvfRFD?XJrwoM)vuYXk%P(dJnNm9%YaqLRDGxrH^;?S9VzS!wt zfblNiF{nYBNRqf`5}kC7twsStM|iXI ziknZQ{0qdB5ag-U=H%g5ToGm3m}R%HVK5tgxqzvJ^m$zX5VeV>)6dMs>bA)wfd$As znXR%d?BX+;2CC3R=n$V*b2_v^OYafbY8(VN^C=itn4QRv_v-Ulmtz+9{jgG4(Eqrf zMT9$z=?~@~eX5yq&^&jaZV^q4I{T(+F&c`XTr(Hvohf5Qp?I?`2znj6m)p*3wgYL2&(}7i5*q zx{s`S4ag_Og*6f#9T3Qjd^>-N)dC`Ze}zrGmfYhD8?a@<_gIKLw^V|DJ_D zOFtDA-Q%?~`lAS|sRY?I!vKAEpbmNbia5IWZ8_R`0zejv$QR-`A+6OtBeJ@|We!w* z1MN$1+-RUXj_p|4=F? zQh)s?%wK_r{+cMGTnjA?|CK1asom_f*m9QGNwD#bqy|j--%G8)7f+2fh+QkBD!D;ds-4%Km>d*PT@6clkP160|Z&u_JT$CQ?}v zbz#OeXk?O6_t=8?qFiq(&w9X&aAs;4g!Xa|BIqwpW7`H6(&Y#s$ws75=8`ANQelV0 z-J6q{^b^8CrH91#b3rzA49e&Yj@#4UMIU{u4CYLMuat8 z`V)gV^jBn7>Uc2+|1b=^HtQEguUepVO$9`RV#gdc9C&wUOZwq_0a(I$Cf8x4QZ6no z7ERDFK%a@-p3mR8T;^gBog(Q%2JOk%>yQ7rX>sDi6c);EMJW2!@&}}o>KNirYqF8c zymZ~Y9lz?X_svY1f^cS_XWj@X!9%Hd*Z$_-+0snF=U#CHSI*n+=NxE2ftl0YV;_GaUA1)$1Ph{ z?vT2IMU~7r^}7eRUo;?-csXa9fX4Imy<#5JwgaHt!+;E{itSqa7h$8=pLyjaOyKW7 zg>~$%2hKe+5`6qZ490=4i08insq%r%crG{GDa!#9iaaF6vp2z;uuGz{8$&W7E>|G)vbs*xyEA*kHI0$$_h6A(R@KtC>)NI@)DwB_FUcO`6-S^PCZ_nP^ zumX=eT2mFO^ioy5>okOHRCicC265s?Hbo9h%OJ+yhWm~eZ~{Kbwkz;^Z?+JHpYFYy zph%ivx~p)YR#ZWL%X6cofyS9Mn1k$~=y6qlfxnl$#EpA7;@=;psdp?f+@XGLwWZmi z)&W}o!5dN{{)|*nfkf-fQ*Z1(hAz%Pzss0Igxk(8tFl;D-@#A)b=YXu=F;E*?wwEO zW(2-_?ZjKVGR@m?PX8oXcgXK1MtrHaFvRRB=1biuDpdela|62OtyY})hy!|jjORRB z3l*5bwS}hP2KEVSU&xgaJxF@cYb4jyw^H6OxViPpqD(^iR)jd zWTh7tk*KdUFQ!=g6-{n|L#2XG!_~b-!G0u%Ddy~?CyEGCbwptt2Tw}QiL$1u-Z*PB zo$Y%pR*PrVv-0{#wPADm8JXUp;So9$)6aBggmqT?Ao-Lkln-FaV;Ynhq&j$qFpO3$ zOp}&1{hYinxr(${igNCKHyyl+S0 z)wy?1QhwIhgh~()?1^`ul%=@Tcdc)CMGL}KSO#)5pn0R!gD!=X*I#9s+L9`sI;+_G zCh?n$8P(KbQSK@O$SFuJsE)0_ZCUf8TUnGK{W&C4=|wsrEw=&Gon4&=FbGBAJ>MlF z?B?C8a%YP?&%snFdbfM6{%|IGHA3ZYz`Ih!?`Ak(k#>=MFm~NZ3s96C=mHdqyp&>- zvL08Rl`pXXXDRo35{})IZ9adTER(hHsIWqgiC7eap0SQUhWZtB&sVTE>U?K^i;vm( zB6K;9Hjyt?3xA|8(pw&Y6%K~c1alRJ#+~pCcu{38ruJA z_J`_}gUy31iQVC7XS@#{?dU$nF_^6u@mY>f#`C8~)tJxv5pM6|k#%oUMVh6JA%aF( zoDOvQ5@^-#eew58RV*8l|L|z#Xy0H#wkr*+)fRrA}V@4)$=ott=Mea|2+gw))u9;hkrQS!hIO5DYZ1(Rr=4qTG;o~o? zXJ2|ge|f((Dk2OqoVix-Is3-d$2obdrm(fo7U{aGsZ#Y}_l+sIiq|p1GzU$nr@y1; zqO5{&9W|4tSiA)^TvH%*H?M`w1BnM0SR+@&w$FVtCI}#D@$|)*8yxO|Pj$D!&D>IW zEU`s6<)RK1@+HV?lnRE4+?*2uLjrC>_&>#KSCcB1CHh;>mzinX2sFOoZmsaUkw`lb zs2sl$;?O6LpfwCN1sJ=HIq6V%t;V^C;#Ng#i(Wola~`~toUt+PcCX_hN2`>M-`!#Ti{Qk15begMYAQ#ye=)5xQWTbZ((6d57s!HQAL5ua->q?HO zB}lBy$T;>|?NIh+Pn>REVsIkMhv#oK5xLCB@#Vzx_49JQ551p$4mLp;qBD8@ox{V1 zVHfCxb)1JO-kO9xu6C}L^z6cXwD{&+#KRK%;?}k1uhS2he%?V(k^%>{C~m2sP48@{ z-IYWXZj*3U!SwOhI~!RB))Viq%^gNslypyVpl1jpsO`{u-V_EDzSoHec}!z$EI`iv zOdtIz`)ZwS79IMOt!-mdd%5bvorpDqb%nk>8?$Ncr&l7ncmxY9zDFBTpK(B*amZ%1 zD0^Qxe!jvMnw(e!aheLcTONZB#z@CiQTwTJrW`0o-1Rwex7O-ibzYb_&7p}*v@tv| z=n%RHvQyIQ(dNQqLxI8-AEd{Z+Up)><$IXSmzEaZyrhk!FoZ~WKh^=pTbN~Jrxg1m z!^v%QW33FP$MhBFk=@0t&r0urSXYsDU#1-a#d3x z56rZLO66RC!C{YX*LwxNrWM1Z>POlgq@;?Gq>4x~C`7@o<5b2#%T3@MN5@z`0r`N{ zbz9JkPmyraCU&7M+vhNSy_2`fA~@G+U_G?i7%N)SzztvDNA?snm@PeXyq!9K$IY?B zKhU{v+L`+iuBH)A8F6BQ>v)`;&<$i@m{kF9Q3XSD@%G?ixlMZwNlw7 zLM3hC)f(}WDWd4yshRm06V(O)Oorz93}uxA)xg!nUpTlo>E7tdU&4KccoL`P=hleR&^MDe~n9!o;FX;Pp$ll4yH?;L= z6m*al!cYH%itN4l=lIHGMtYqMGg-EohH; zC(}c@@%$`sgl_UDS!r^`F1ld>6uM|$V0%x>phZ@CRXQUm2s_LK*LWqB-4>E|_FjhX zuySa)s;%fi9^-ezx()Q&L~`1=zs@H__vdkL5xq{@Ln=LE2VTSS8-f=Pzt-*3eZAxG z*HZ`{KP1&G$oQsXj8QQhUdo)A0LeQmN(GJX6g9y7kK{tAQObRNXN5b$vu(JG=WyF zsz+-5w0_4UwsTY-rMt(ftb_AohustM2*_mRW#adN3seixxgDs(zZwVZ?r5<{gJX}7 zpIZ_4BxnTY_Dr5TzC(_KiIxIKZ{XPd8!@K!O$6IJ_frx0@CkAB8g#^=usg)PZ5@c~ zIU~ku0sC||75)nWiNOPn{RmWkD(#Q{8*&a5GpG55v8b9i_vdldJZ^5TGcqt&+frz~ zWOJ&Y*vWJP1olNd{wjvu??O)FFI@JpG%sf9&7a7tOS+jq>%E$ZGkf_Wg-gT}+UIYG zp!g~Rb!j=|k9z=|ZKIPu_aB@cKV>dO;RtkKivl)*hXQ-AlG-gTz~5(sw;9JRX9b9u zJ~TEW%S-^UoG7kA3;MsopV<=0p{3&=c>0YlV!p%UIE&z1`VPt717Ow?F zs9)tt5#j!u^~E~fTVI6_&Z<=t1_dIO_1+a1^XtqA=kcq$HZWneW1sx27B~pEnmEn& zTMFhB=%ypUEQrB%%~X7XC_E7-+ih$3%hgUQK-`7`8Ka{OF?pIo^&bI2K)w)6yaeFV z9=7z`WM_V;l2iN^+}UgUL&fHA+CINo2{;vwXaNoLzjW}^g8r1s`I~&!UOVwgt)kAG zGuI#*Y#%RI2K=T75T^dn5Bj^f68x7)kT*CU%AM%#afal#Sxx>E|4Of*Y4*UqDEfH$ zx5CZ@;~(SvyGq_~$^=2XYX*Ih=`ZvS(qJO{;(seU5tWUAGDNtkga<`mG`YjeqW^fH z@fRWFe`|3O)rBai$2(`^l{uklO@9$3x(fMI4Cx=aA6;^YGzoJahqJ#u@P7jHk9>|s zUBP`EDcN5LDb17rZ!a@yumx<*oHnuG`R#!wfqx0+e%9Nrc&^)jnP?Q$|KjE6INB60 zn&I;%%|tP$Uw-rbmSqqAHAF=K|0?>QrV*a+XFA4{}RmqU!RQ3wX+>3G~yt| VNVU?Bai@Tv(gSt*;``qP5hkv&4P9qb@@) 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ⅇ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 literal 0 HcmV?d00001 diff --git a/docs/en-US/plugin-niciranvp-about.xml b/docs/en-US/plugin-niciranvp-about.xml index 8d2e20e7756..cfab83c73c3 100644 --- a/docs/en-US/plugin-niciranvp-about.xml +++ b/docs/en-US/plugin-niciranvp-about.xml @@ -1,5 +1,5 @@ - %BOOK_ENTITIES; diff --git a/docs/en-US/plugin-niciranvp-devicemanagement.xml b/docs/en-US/plugin-niciranvp-devicemanagement.xml index 57b8eee9d7d..761c39f3179 100644 --- a/docs/en-US/plugin-niciranvp-devicemanagement.xml +++ b/docs/en-US/plugin-niciranvp-devicemanagement.xml @@ -21,27 +21,15 @@ under the License. -->
    - Device-management - In &PRODUCT; 4.0.x each Nicira NVP setup is considered a "device" that can be added and removed from a physical network. To complete the configuration of the Nicira NVP plugin a device needs to be added to the physical network using the "addNiciraNVPDevice" API call. The plugin is now enabled on the physical network and any guest networks created on that network will be provisioned using the Nicira NVP Controller. - The plugin introduces a set of new API calls to manage the devices, see below or refer to the API reference. - - addNiciraNvpDevice - - - physicalnetworkid: the UUID of the physical network on which the device is configured - hostname: the IP address of the NVP controller - username: the username for access to the NVP API - password: the password for access to the NVP API - transportzoneuuid: the UUID of the transportzone - - - deleteNiciraNVPDevice - - - nvpdeviceid: the UUID of the device - - - listNiciraNVPDevices - + Device Management + In &PRODUCT; a Nicira NVP setup is considered a "device" that can be added and removed from a physical network. To complete the configuration of the Nicira NVP plugin a device needs to be added to the physical network. Press the "Add NVP Controller" button on the provider panel and enter the configuration details. + + + + + + nvp-physical-network-stt.png: a screenshot of the device configuration popup. + +
    diff --git a/docs/en-US/plugin-niciranvp-features.xml b/docs/en-US/plugin-niciranvp-features.xml index c346bfb64e3..e439f1b4923 100644 --- a/docs/en-US/plugin-niciranvp-features.xml +++ b/docs/en-US/plugin-niciranvp-features.xml @@ -22,12 +22,63 @@ -->
    Features of the Nicira NVP Plugin - In &PRODUCT; release 4.0.0-incubating this plugin supports the Connectivity service. This service is responsible for creating Layer 2 networks supporting the networks created by Guests. In other words when an tenant creates a new network, instead of the traditional VLAN a logical network will be created by sending the appropriate calls to the Nicira NVP Controller. - The plugin has been tested with Nicira NVP versions 2.1.0, 2.2.0 and 2.2.1 - In &PRODUCT; 4.0.0-incubating only the XenServer hypervisor is supported for use in - combination with Nicira NVP. - In &PRODUCT; 4.1.0-incubating both KVM and XenServer hypervisors are - supported. - In &PRODUCT; 4.0.0-incubating the UI components for this plugin are not complete, - configuration is done by sending commands to the API. + The following table lists the CloudStack network services provided by the Nicira NVP Plugin. + + Supported Services + + + + Network Service + CloudStack version + NVP version + + + + + Virtual Networking + >= 4.0 + >= 2.2.1 + + + Source NAT + >= 4.1 + >= 3.0.1 + + + Static NAT + >= 4.1 + >= 3.0.1 + + + Port Forwarding + >= 4.1 + >= 3.0.1 + + + +
    + The Virtual Networking service was originally called 'Connectivity' in CloudStack 4.0 + The following hypervisors are supported by the Nicira NVP Plugin. + + Supported Hypervisors + + + + Hypervisor + CloudStack version + + + + + XenServer + >= 4.0 + + + KVM + >= 4.1 + + + +
    + Please refer to the Nicira NVP configuration guide on how to prepare the hypervisors for Nicira NVP integration.
    diff --git a/docs/en-US/plugin-niciranvp-introduction.xml b/docs/en-US/plugin-niciranvp-introduction.xml index 9c1d42df32d..a06f12317e5 100644 --- a/docs/en-US/plugin-niciranvp-introduction.xml +++ b/docs/en-US/plugin-niciranvp-introduction.xml @@ -22,5 +22,8 @@ -->
    Introduction to the Nicira NVP Plugin - The Nicira NVP plugin allows CloudStack to use the Nicira solution for virtualized network as a provider for CloudStack networks and services. + The Nicira NVP plugin adds Nicira NVP as one of the available SDN implementations in + CloudStack. With the plugin an exisiting Nicira NVP setup can be used by CloudStack to + implement isolated guest networks and to provide additional services like routing and + NAT.
    diff --git a/docs/en-US/plugin-niciranvp-networkofferings.xml b/docs/en-US/plugin-niciranvp-networkofferings.xml new file mode 100644 index 00000000000..b30437e97ba --- /dev/null +++ b/docs/en-US/plugin-niciranvp-networkofferings.xml @@ -0,0 +1,131 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
    + Network Offerings + Using the Nicira NVP plugin requires a network offering with Virtual Networking enabled and configured to use the NiciraNvp element. Typical use cases combine services from the Virtual Router appliance and the Nicira NVP plugin. + + Isolated network offering with regular services from the Virtual Router. + + + + Service + Provider + + + + + VPN + VirtualRouter + + + DHCP + VirtualRouter + + + DNS + VirtualRouter + + + Firewall + VirtualRouter + + + Load Balancer + VirtualRouter + + + User Data + VirtualRouter + + + Source NAT + VirtualRouter + + + Static NAT + VirtualRouter + + + Post Forwarding + VirtualRouter + + + Virtual Networking + NiciraNVP + + + +
    + + + + + + nvp-physical-network-stt.png: a screenshot of a network offering. + + + The tag in the network offering should be set to the name of the physical network with the NVP provider. + Isolated network with network services. The virtual router is still required to provide network services like dns and dhcp. + + Isolated network offering with network services + + + + Service + Provider + + + + + DHCP + VirtualRouter + + + DNS + VirtualRouter + + + User Data + VirtualRouter + + + Source NAT + NiciraNVP + + + Static NAT + NiciraNVP + + + Post Forwarding + NiciraNVP + + + Virtual Networking + NiciraNVP + + + +
    + +
    diff --git a/docs/en-US/plugin-niciranvp-physicalnet.xml b/docs/en-US/plugin-niciranvp-physicalnet.xml new file mode 100644 index 00000000000..d3202905fb1 --- /dev/null +++ b/docs/en-US/plugin-niciranvp-physicalnet.xml @@ -0,0 +1,37 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
    + Zone Configuration + &PRODUCT; needs to have at least one physical network with the isolation method set to "STT". This network should be enabled for the Guest traffic type. + The Guest traffic type should be configured with the traffic label that matches the name of + the Integration Bridge on the hypervisor. See the Nicira NVP User Guide for more details + on how to set this up in XenServer or KVM. + + + + + + nvp-physical-network-stt.png: a screenshot of a physical network with the STT isolation type + + +
    diff --git a/docs/en-US/plugin-niciranvp-preparations.xml b/docs/en-US/plugin-niciranvp-preparations.xml index 762c941fd13..60725591fda 100644 --- a/docs/en-US/plugin-niciranvp-preparations.xml +++ b/docs/en-US/plugin-niciranvp-preparations.xml @@ -22,17 +22,16 @@ -->
    Prerequisites - Before enabling the Nicira NVP plugin the NVP Controller needs to be configured. Please review the NVP User Guide on how to do that. - &PRODUCT; needs to have at least one physical network with the isolation method set to "STT". This network should be enabled for the Guest traffic type. - The Guest traffic type should be configured with the traffic label that matches the name of - the Integration Bridge on the hypervisor. See the Nicira NVP User Guide for more details - on how to set this up in XenServer or KVM. + Before enabling the Nicira NVP plugin the NVP Controller needs to be configured. Please review the NVP User Guide on how to do that. Make sure you have the following information ready: The IP address of the NVP Controller The username to access the API The password to access the API The UUID of the Transport Zone that contains the hypervisors in this Zone - The UUID of the Physical Network that will be used for the Guest networks + + The UUID of the Gateway Service used to provide router and NAT services. + + The gateway service uuid is optional and is used for Layer 3 services only (SourceNat, StaticNat and PortForwarding)
    diff --git a/docs/en-US/plugin-niciranvp-provider.xml b/docs/en-US/plugin-niciranvp-provider.xml index 80fb2273238..8694478b483 100644 --- a/docs/en-US/plugin-niciranvp-provider.xml +++ b/docs/en-US/plugin-niciranvp-provider.xml @@ -22,21 +22,15 @@ -->
    Enabling the service provider - To allow CloudStack to use the Nicira NVP Plugin the network service provider needs to be enabled on the physical network. The following sequence of API calls will enable the network service provider - - addNetworkServiceProvider - - - name = "NiciraNvp" - physicalnetworkid = <the uuid of the physical network> - - - updateNetworkServiceProvider - - - id = <the provider uuid returned by the previous call> - state = "Enabled" - - - + The Nicira NVP provider is disabled by default. Navigate to the "Network Service Providers" configuration of the physical network with the STT isolation type. Navigate to the Nicira NVP provider and press the "Enable Provider" button. + CloudStack 4.0 does not have the UI interface to configure the Nicira NVP plugin. Configuration needs to be done using the API directly. + + + + + + nvp-physical-network-stt.png: a screenshot of an enabled Nicira NVP provider + + +
    \ No newline at end of file diff --git a/docs/en-US/plugin-niciranvp-revisions.xml b/docs/en-US/plugin-niciranvp-revisions.xml index b8e6935c5d1..b58d3336aba 100644 --- a/docs/en-US/plugin-niciranvp-revisions.xml +++ b/docs/en-US/plugin-niciranvp-revisions.xml @@ -40,6 +40,20 @@ + + 1-0 + Wed May 22 2013 + + Hugo + Trippaers + hugo@apache.org + + + + Documentation updated for &PRODUCT; 4.1.0 + + + diff --git a/docs/en-US/plugin-niciranvp-tables.xml b/docs/en-US/plugin-niciranvp-tables.xml index 4f816550b30..615f3494c09 100644 --- a/docs/en-US/plugin-niciranvp-tables.xml +++ b/docs/en-US/plugin-niciranvp-tables.xml @@ -23,29 +23,84 @@
    Database tables The following tables are added to the cloud database for the Nicira NVP Plugin - - nicira_nvp_nic_map, contains a mapping from nic to logical switch port - - - id - logicalswitch, uuid of the logical switch this port is connected to - logicalswitchport, uuid of the logical switch port for this nic - nic, the CloudStack uuid for this nic, reference to the nics table - - - - - external_nicira_nvp_devices, contains all configured devices - - - id - uuid - physical_network_id, the physical network this device is configured on - provider_name, set to "NiciraNvp" - device_name, display name for this device - host_id, reference to the host table with the device configuration - - - - + + nicira_nvp_nic_map + + + + id + auto incrementing id + + + logicalswitch + uuid of the logical switch this port is connected to + + + logicalswitchport + uuid of the logical switch port for this nic + + + nic + the &PRODUCT; uuid for this nic, reference to the nics table + + + +
    + + + external_nicira_nvp_devices + + + + id + auto incrementing id + + + uuid + UUID identifying this device + + + physical_network_id + the physical network this device is configured on + + + provider_name + NiciraNVP + + + device_name + display name for this device + + + host_id + reference to the host table with the device configuration + + + +
    + + + nicira_nvp_router_map + + + + id + auto incrementing id + + + logicalrouter_uuid + uuid of the logical router + + + network_id + id of the network this router is linked to + + + +
    + + + nicira_nvp_router_map is only available in &PRODUCT; 4.1 and above + +
    \ No newline at end of file diff --git a/docs/en-US/plugin-niciranvp-usage.xml b/docs/en-US/plugin-niciranvp-usage.xml index 76f9a0b5b05..9f04c382bd6 100644 --- a/docs/en-US/plugin-niciranvp-usage.xml +++ b/docs/en-US/plugin-niciranvp-usage.xml @@ -21,10 +21,13 @@ under the License. --> - Using the Nicira NVP Plugin + Configuring the Nicira NVP Plugin - - - + + + + diff --git a/docs/en-US/plugin-niciranvp-guide.xml b/docs/en-US/plugin-niciranvp-vpc.xml similarity index 65% rename from docs/en-US/plugin-niciranvp-guide.xml rename to docs/en-US/plugin-niciranvp-vpc.xml index 89c9871021d..a43c5fa85d3 100644 --- a/docs/en-US/plugin-niciranvp-guide.xml +++ b/docs/en-US/plugin-niciranvp-vpc.xml @@ -1,11 +1,10 @@ - + %BOOK_ENTITIES; %xinclude; ]> - - - Plugin Guide for the Nicira NVP Plugin - - - + + Using the Nicira NVP plugin with VPC + + + + + diff --git a/docs/en-US/plugin-niciranvp-vpcfeatures.xml b/docs/en-US/plugin-niciranvp-vpcfeatures.xml new file mode 100644 index 00000000000..a8d8194e9ba --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcfeatures.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
    + Supported VPC features + The Nicira NVP plugin supports &PRODUCT; VPC to a certain extent. Starting with &PRODUCT; version 4.1 VPCs can be deployed using NVP isolated networks. + It is not possible to use a Nicira NVP Logical Router for as a VPC Router + It is not possible to connect a private gateway using a Nicira NVP Logical Switch +
    diff --git a/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml b/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml new file mode 100644 index 00000000000..141006ee350 --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml @@ -0,0 +1,81 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
    + VPC Network Offerings + The VPC needs specific network offerings with the VPC flag enabled. Otherwise these network offerings are identical to regular network offerings. To allow VPC networks with a Nicira NVP isolated network the offerings need to support the Virtual Networking service with the NiciraNVP provider. + In a typical configuration two network offerings need to be created. One with the loadbalancing service enabled and one without loadbalancing. + + VPC Network Offering with Loadbalancing + + + + Service + Provider + + + + + VPN + VpcVirtualRouter + + + DHCP + VpcVirtualRouter + + + DNS + VpcVirtualRouter + + + Load Balancer + VpcVirtualRouter + + + User Data + VpcVirtualRouter + + + Source NAT + VpcVirtualRouter + + + Static NAT + VpcVirtualRouter + + + Post Forwarding + VpcVirtualRouter + + + NetworkACL + VpcVirtualRouter + + + Virtual Networking + NiciraNVP + + + +
    + +
    diff --git a/docs/en-US/plugin-niciranvp-vpcoffering.xml b/docs/en-US/plugin-niciranvp-vpcoffering.xml new file mode 100644 index 00000000000..292621e516c --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcoffering.xml @@ -0,0 +1,38 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
    + VPC Offering with Nicira NVP + To allow a VPC to use the Nicira NVP plugin to provision networks, a new VPC offering needs to be created which allows the Virtual Networking service to be implemented by NiciraNVP. + This is not currently possible with the UI. The API does provide the proper calls to create a VPC offering with Virtual Networking enabled. However due to a limitation in the 4.1 API it is not possible to select the provider for this network service. To configure the VPC offering with the NiciraNVP provider edit the database table 'vpc_offering_service_map' and change the provider to NiciraNvp for the service 'Connectivity' + It is also possible to update the default VPC offering by adding a row to the + 'vpc_offering_service_map' with service 'Connectivity' and provider 'NiciraNvp' + + + + + + nvp-physical-network-stt.png: a screenshot of the mysql table. + + + When creating a new VPC offering please note that the UI does not allow you to select a VPC offering yet. The VPC needs to be created using the API with the offering UUID. +
    From 2336d478beca8c3d17fbf76bbf09f915906bdea8 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Thu, 23 May 2013 23:19:03 +0200 Subject: [PATCH 095/201] debian: When building packages run a Maven clean first --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index e381b1a8ebe..48485bb9d9b 100755 --- a/debian/rules +++ b/debian/rules @@ -34,7 +34,7 @@ build: build-indep build-indep: build-indep-stamp build-indep-stamp: configure - mvn package -Pawsapi -DskipTests -Dsystemvm \ + mvn clean package -Pawsapi -DskipTests -Dsystemvm \ -Dcs.replace.properties=replace.properties.tmp \ ${ACS_BUILD_OPTS} touch $@ From e8fbee0e18383a4ae07b62c4dafdadf742ec62bb Mon Sep 17 00:00:00 2001 From: Anthony Xu Date: Thu, 23 May 2013 14:18:09 -0700 Subject: [PATCH 096/201] firewall service is not supported in shared SG enabled network offering , remove it --- .../cloud/upgrade/dao/Upgrade410to420.java | 32 +++++++++++++++++++ setup/db/db/schema-410to420.sql | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index c03d377cbe0..95abe5f161e 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -75,6 +75,7 @@ public class Upgrade410to420 implements DbUpgrade { updateNetworkACLs(conn); addHostDetailsIndex(conn); updateNetworksForPrivateGateways(conn); + removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -747,4 +748,35 @@ public class Upgrade410to420 implements DbUpgrade { throw new CloudRuntimeException("Failed to update private networks with VPC id.", e); } } + + private void removeFirewallServiceFromSharedNetworkOfferingWithSGService(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = conn.prepareStatement("select id from `cloud`.`network_offerings` where unique_name='DefaultSharedNetworkOfferingWithSGService'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + // remove Firewall service for SG shared network offering + pstmt = conn.prepareStatement("DELETE `cloud`.`ntwk_offering_service_map` where network_offering_id=? and service='Firewall'"); + pstmt.setLong(1, id); + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to remove Firewall service for SG shared network offering.", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } + } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index ea7a18df0ff..b5480359edd 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1710,5 +1710,5 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'VpcMa -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; - +UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; From 026c2cec6d3cb42c32929c9ed3ee417b7771b667 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Thu, 23 May 2013 14:34:26 -0700 Subject: [PATCH 097/201] CLOUDSTACK-2504: UI - create network offering dialog - pass specifyIpRanges=false for Isolated Network. --- ui/scripts/configuration.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 808b34289d7..9932cdc3aa6 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -1919,26 +1919,22 @@ inputData['isPersistent'] = false; } else if (inputData['guestIpType'] == "Isolated") { //specifyVlan checkbox is shown - if (inputData['specifyVlan'] == 'on') { //specifyVlan checkbox is checked + inputData['specifyIpRanges'] = false; + + if (inputData['specifyVlan'] == 'on') { //specifyVlan checkbox is checked inputData['specifyVlan'] = true; - inputData['specifyIpRanges'] = true; - - - - } else { //specifyVlan checkbox is unchecked inputData['specifyVlan'] = false; - inputData['specifyIpRanges'] = false; + } - if(inputData['isPersistent'] == 'on') { //It is a persistent network - inputData['isPersistent'] = true; - } - else { //Isolated Network with Non-persistent network - inputData['isPersistent'] = false; - } - + if(inputData['isPersistent'] == 'on') { //It is a persistent network + inputData['isPersistent'] = true; + } + else { //Isolated Network with Non-persistent network + inputData['isPersistent'] = false; + } } From b1f4c8e89af1d79f2d5cba03910e93b40e3c0859 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Thu, 23 May 2013 23:46:55 +0200 Subject: [PATCH 098/201] Fix a small typo in a log line --- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index f4875377f93..c65514b1b31 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -358,7 +358,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (s_logger.isDebugEnabled()) { - s_logger.debug("Allocaing disks for " + vm); + s_logger.debug("Allocating disks for " + vm); } if (template.getFormat() == ImageFormat.ISO) { From a46b4d8273e9033e55172bf2d00845820bc9511a Mon Sep 17 00:00:00 2001 From: Min Chen Date: Thu, 23 May 2013 15:14:43 -0700 Subject: [PATCH 099/201] CLOUDSTACK-2656: UUID column for all 4.0 schema entities should be populated when they are upgraded to 4.1 --- setup/db/db/schema-40to410.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index 381a4cea612..acc29a2eb7f 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -184,6 +184,7 @@ UPDATE `cloud`.`alert` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`async_job` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`cluster` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`data_center` set uuid=id WHERE uuid is NULL; +UPDATE `cloud`.`dc_storage_network_ip_range` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`disk_offering` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`domain` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`event` set uuid=id WHERE uuid is NULL; @@ -217,6 +218,7 @@ UPDATE `cloud`.`security_group` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`security_group_rule` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`snapshot_schedule` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`snapshots` set uuid=id WHERE uuid is NULL; +UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`static_routes` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`storage_pool` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`swift` set uuid=id WHERE uuid is NULL; From cf8ff0cc654e5da4cf7510b964b9ef6cd828c90b Mon Sep 17 00:00:00 2001 From: Min Chen Date: Thu, 23 May 2013 15:43:14 -0700 Subject: [PATCH 100/201] Populate UUID column for new data introduced in 4.2.0. --- setup/db/db/schema-410to420.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index b5480359edd..885eff46132 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -353,8 +353,8 @@ ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `lxc_network_lab UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC' WHERE name='hypervisor.list'; -INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) - VALUES (10, 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); +INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) + VALUES (10, UUID(), 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); ALTER TABLE `cloud`.`user_vm` MODIFY user_data TEXT(32768); From f92db64c78778e58821073971152167472ef340d Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Thu, 23 May 2013 15:59:03 -0700 Subject: [PATCH 101/201] Install wizard UI: Add preinstall hook For fresh install, adds hook to install wizard UI to show a custom 'step' before the initial welcome screen. Pre-install specified by providing 'cloudStack.preInstall,' which returns a jQuery object to be displayed. It passes args.complete, which when called will proceed to the first step of the install wizard. --- ui/scripts/ui-custom/installWizard.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ui/scripts/ui-custom/installWizard.js b/ui/scripts/ui-custom/installWizard.js index 86919f9fa41..9f1f4c761e5 100644 --- a/ui/scripts/ui-custom/installWizard.js +++ b/ui/scripts/ui-custom/installWizard.js @@ -298,6 +298,17 @@ * Layout/behavior for each step in wizard */ var steps = { + start: function(args) { + if (cloudStack.preInstall) { + return cloudStack.preInstall({ + complete: function() { + goTo('intro'); + } + }); + } + + return steps.intro(args); + }, intro: function(args) { var $intro = $('
    ').addClass('intro what-is-cloudstack'); var $title = $('
    ').addClass('title').html(_l('label.what.is.cloudstack')); @@ -775,7 +786,7 @@ } }; - var initialStep = steps.intro().addClass('step'); + var initialStep = steps.start().addClass('step'); showDiagram(''); From 7e6f3f94ba467f8f58ed6b130055bdd6df73815a Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Thu, 23 May 2013 10:24:44 -0700 Subject: [PATCH 102/201] CLOUDSTACK-2628: added networkId parameter to the list of request parameters in listLoadBalancerRules API --- .../ListLoadBalancerRulesCmd.java | 9 +++++++++ .../api/response/LoadBalancerResponse.java | 11 ++++++++++- .../src/com/cloud/api/ApiResponseHelper.java | 19 +++++++++++-------- .../lb/LoadBalancingRulesManagerImpl.java | 6 ++++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java index e022cc78db0..21d5b2a440e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; @@ -62,6 +63,10 @@ public class ListLoadBalancerRulesCmd extends BaseListTaggedResourcesCmd { @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "the availability zone ID") private Long zoneId; + + @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, + description = "list by network id the rule belongs to") + private Long networkId; // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// @@ -86,6 +91,10 @@ public class ListLoadBalancerRulesCmd extends BaseListTaggedResourcesCmd { public Long getZoneId() { return zoneId; } + + public Long getNetworkId() { + return networkId; + } // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// diff --git a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java index 79b01b17ff2..0f180970fc7 100644 --- a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java +++ b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java @@ -57,10 +57,14 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti @SerializedName(ApiConstants.ALGORITHM) @Param(description = "the load balancer algorithm (source, roundrobin, leastconn)") private String algorithm; + + @SerializedName(ApiConstants.NETWORK_ID) + @Param(description = "the id of the guest network the lb rule belongs to") + private String networkId; @SerializedName(ApiConstants.CIDR_LIST) @Param(description="the cidr list to forward traffic from") private String cidrList; - + @SerializedName(ApiConstants.ACCOUNT) @Param(description = "the account of the load balancer rule") private String accountName; @@ -89,6 +93,7 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with load balancer", responseObject = ResourceTagResponse.class) private List tags; + public void setId(String id) { this.id = id; @@ -160,5 +165,9 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti public void setTags(List tags) { this.tags = tags; } + + public void setNetworkId(String networkId) { + this.networkId = networkId; + } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index fc1c6a0be63..540c8e9a4d7 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -34,12 +34,6 @@ import java.util.TimeZone; import javax.inject.Inject; -import com.cloud.network.vpc.NetworkACL; -import com.cloud.network.vpc.NetworkACLItem; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOffering; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -49,8 +43,6 @@ import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; -import org.apache.cloudstack.region.PortableIp; -import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ApplicationLoadBalancerInstanceResponse; import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse; @@ -146,6 +138,8 @@ import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.api.response.VpnUsersResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.usage.Usage; @@ -241,6 +235,12 @@ import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; import com.cloud.network.security.SecurityRule.SecurityRuleType; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcOffering; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Detail; @@ -776,6 +776,9 @@ public class ApiResponseHelper implements ResponseGenerator { tagResponses.add(tagResponse); } lbResponse.setTags(tagResponses); + + Network ntwk = ApiDBUtils.findNetworkById(loadBalancer.getNetworkId()); + lbResponse.setNetworkId(ntwk.getUuid()); lbResponse.setObjectName("loadbalancer"); return lbResponse; diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 520dd763667..0118ca534e1 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -1902,6 +1902,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements String name = cmd.getLoadBalancerRuleName(); String keyword = cmd.getKeyword(); Long instanceId = cmd.getVirtualMachineId(); + Long networkId = cmd.getNetworkId(); Map tags = cmd.getTags(); Account caller = UserContext.current().getCaller(); @@ -1922,6 +1923,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); + sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); if (instanceId != null) { SearchBuilder lbVMSearch = _lb2VmMapDao.createSearchBuilder(); @@ -1979,6 +1981,10 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (zoneId != null) { sc.setJoinParameters("ipSearch", "zoneId", zoneId); } + + if (networkId != null) { + sc.setParameters("networkId", networkId); + } if (tags != null && !tags.isEmpty()) { int count = 0; From 780b45e245aba1ca99d12fd4a8de88999642b4ae Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Thu, 23 May 2013 16:32:34 -0700 Subject: [PATCH 103/201] CLOUDSTACK-2657: listTemplatePermissions API should also include the owner of the template to the list of users having permission to launch Changes: - Add template owner to the list of users --- server/src/com/cloud/template/TemplateManagerImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index d4976cdc357..517d4ba80d7 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -1553,6 +1553,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, accountNames.add(acct.getAccountName()); } } + + // also add the owner if not public + if (!template.isPublicTemplate()) { + Account templateOwner = _accountDao.findById(template.getAccountId()); + accountNames.add(templateOwner.getAccountName()); + } + return accountNames; } From 07715b91afd44c1ebc0a6977923a0de0f5c1b1ee Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Thu, 23 May 2013 18:45:38 -0700 Subject: [PATCH 104/201] CLOUDSTACK-2639: Add flag for booting complete Don't execute any command before VR complete booting up process. --- .../config/etc/init.d/cloud-early-config | 3 +++ patches/systemvm/debian/config/etc/rc.local | 3 +++ .../opt/cloud/bin/get_template_version.sh | 26 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index d918670edab..ca3b970210b 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -33,6 +33,9 @@ PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" # Fix haproxy directory issue mkdir -p /var/lib/haproxy +# Clear boot up flag, it would be created by rc.local after boot up done +rm /var/cache/cloud/boot_up_done + [ -x /sbin/ifup ] || exit 0 . /lib/lsb/init-functions diff --git a/patches/systemvm/debian/config/etc/rc.local b/patches/systemvm/debian/config/etc/rc.local index cb434a23526..6119497596b 100755 --- a/patches/systemvm/debian/config/etc/rc.local +++ b/patches/systemvm/debian/config/etc/rc.local @@ -13,3 +13,6 @@ do logger -t cloud "Stopping $svc" service $svc stop done + +date > /var/cache/cloud/boot_up_done +logger -t cloud "Boot up process done" diff --git a/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh b/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh index 298bc380f82..233ec983f8e 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh @@ -16,5 +16,31 @@ # specific language governing permissions and limitations # under the License. +# As the last command send to router before any rules operation, wait until boot up done + +__TIMEOUT=60 +__FLAGFILE=/var/cache/cloud/boot_up_done +done=0 +for i in `seq 1 $(($__TIMEOUT * 10))` +do + if [ -e $__FLAGFILE ] + then + done=1 + break + fi + sleep 0.1 + if [ $((i % 10)) -eq 0 ] + then + logger -t cloud "Waiting for VM boot up done for one second" + fi +done + +if [ -z $done ] +then + # declare we failed booting process + echo "Waited 60 seconds but boot up haven't been completed" + exit +fi + echo -n `cat /etc/cloudstack-release`'&' cat /var/cache/cloud/cloud-scripts-signature From 2276760b3b38380c61097a15cc0cb3325a565b3d Mon Sep 17 00:00:00 2001 From: Mice Xia Date: Fri, 24 May 2013 11:27:16 +0800 Subject: [PATCH 105/201] fix CLOUDSTACK-2649 createLoadBalancerRule API:both ports getting same value(public port value assigned to private port) --- .../src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 0118ca534e1..1d7b3121158 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -1395,7 +1395,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements Purpose.LoadBalancing, FirewallRuleType.User, networkId, null); LoadBalancerVO newRule = new LoadBalancerVO(xId, name, description, - sourceIpId, srcPort, srcPort, algorithm, + sourceIpId, srcPort, destPort, algorithm, networkId, ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId()); // verify rule is supported by Lb provider of the network From 704471e6deb1f72b6cc5a9fdcad15927dfc689a8 Mon Sep 17 00:00:00 2001 From: Jayapal Date: Mon, 20 May 2013 11:00:51 +0530 Subject: [PATCH 106/201] CLOUDSTACK-2386 Fixed srx firewall icmp rule Signed-off-by: Abhinandan Prateek --- .../JuniperSRXExternalFirewallElement.java | 1 + .../network/resource/JuniperSrxResource.java | 35 +++++++++---------- .../ExternalFirewallDeviceManagerImpl.java | 4 ++- utils/src/com/cloud/utils/net/NetUtils.java | 2 ++ 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index a429306a680..c00d99abf88 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -242,6 +242,7 @@ PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, Junip // Set capabilities for Firewall service Map firewallCapabilities = new HashMap(); firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); + firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp,all"); firewallCapabilities.put(Capability.MultipleIps, "true"); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress"); diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java index a0068c3784c..fd065d58f87 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java @@ -750,7 +750,7 @@ public class JuniperSrxResource implements ServerResource { s_logger.debug(msg); } - private void shutdownGuestNetwork(GuestNetworkType type, long accountId, Long publicVlanTag, String sourceNatIpAddress, long privateVlanTag, String privateGateway, String privateSubnet, long privateCidrSize) throws ExecutionException { + private void shutdownGuestNetwork(GuestNetworkType type, long accountId, Long publicVlanTag, String sourceNatIpAddress, long privateVlanTag, String privateGateway, String privateSubnet, long privateCidrSize) throws ExecutionException { // Remove static and destination NAT rules for the guest network removeStaticAndDestNatRulesInPrivateVlan(privateVlanTag, privateGateway, privateCidrSize); @@ -766,10 +766,10 @@ public class JuniperSrxResource implements ServerResource { manageSourceNatPool(SrxCommand.DELETE, sourceNatIpAddress); manageProxyArp(SrxCommand.DELETE, publicVlanTag, sourceNatIpAddress); manageUsageFilter(SrxCommand.DELETE, _usageFilterIPOutput, privateSubnet, null, genIpFilterTermName(sourceNatIpAddress)); - manageUsageFilter(SrxCommand.DELETE, _usageFilterIPInput, sourceNatIpAddress, null, genIpFilterTermName(sourceNatIpAddress)); + manageUsageFilter(SrxCommand.DELETE, _usageFilterIPInput, sourceNatIpAddress, null, genIpFilterTermName(sourceNatIpAddress)); } else if (type.equals(GuestNetworkType.INTERFACE_NAT)) { manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanOutput, null, privateVlanTag, null); - manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanInput, null, privateVlanTag, null); + manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanInput, null, privateVlanTag, null); } String msg = "Shut down guest network with type " + type +". Guest VLAN tag: " + privateVlanTag + ", guest gateway: " + privateGateway; @@ -841,21 +841,24 @@ public class JuniperSrxResource implements ServerResource { commitConfiguration(); } else { for (FirewallRuleTO rule : rules) { - int startPort = 0, endPort = 0; + int startPort = NetUtils.PORT_RANGE_MIN, endPort = NetUtils.PORT_RANGE_MAX; if (rule.getSrcPortRange() != null) { startPort = rule.getSrcPortRange()[0]; endPort = rule.getSrcPortRange()[1]; - FirewallFilterTerm term = new FirewallFilterTerm(genIpIdentifier(rule.getSrcIp()) + "-" + String.valueOf(rule.getId()), rule.getSourceCidrList(), - rule.getSrcIp(), rule.getProtocol(), startPort, endPort, - rule.getIcmpType(), rule.getIcmpCode(), genIpIdentifier(rule.getSrcIp()) + _usageFilterIPInput.getCounterIdentifier()); - if (!rule.revoked()) { - manageFirewallFilter(SrxCommand.ADD, term, _publicZoneInputFilterName); - } else { - manageFirewallFilter(SrxCommand.DELETE, term, _publicZoneInputFilterName); - } } - commitConfiguration(); + + FirewallFilterTerm term = new FirewallFilterTerm(genIpIdentifier(rule.getSrcIp()) + "-" + String.valueOf(rule.getId()), rule.getSourceCidrList(), + rule.getSrcIp(), rule.getProtocol(), startPort, endPort, + rule.getIcmpType(), rule.getIcmpCode(), genIpIdentifier(rule.getSrcIp()) + _usageFilterIPInput.getCounterIdentifier()); + if (!rule.revoked()) { + manageProxyArp(SrxCommand.ADD, getVlanTag(rule.getSrcVlanTag()), rule.getSrcIp()); + manageFirewallFilter(SrxCommand.ADD, term, _publicZoneInputFilterName); + } else { + manageFirewallFilter(SrxCommand.DELETE, term, _publicZoneInputFilterName); + manageProxyArp(SrxCommand.DELETE, getVlanTag(rule.getSrcVlanTag()), rule.getSrcIp()); + } } + commitConfiguration(); } return new Answer(cmd); @@ -925,7 +928,6 @@ public class JuniperSrxResource implements ServerResource { } private void addStaticNatRule(Long publicVlanTag, String publicIp, String privateIp, List rules) throws ExecutionException { - manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp); manageStaticNatRule(SrxCommand.ADD, publicIp, privateIp); manageAddressBookEntry(SrxCommand.ADD, _privateZone, privateIp, null); @@ -937,7 +939,6 @@ public class JuniperSrxResource implements ServerResource { private void removeStaticNatRule(Long publicVlanTag, String publicIp, String privateIp) throws ExecutionException { manageStaticNatRule(SrxCommand.DELETE, publicIp, privateIp); - manageProxyArp(SrxCommand.DELETE, publicVlanTag, publicIp); // Remove any existing security policy and clean up applications removeSecurityPolicyAndApplications(SecurityPolicyType.STATIC_NAT, privateIp); @@ -1196,8 +1197,7 @@ public class JuniperSrxResource implements ServerResource { } private void addDestinationNatRule(Protocol protocol, Long publicVlanTag, String publicIp, String privateIp, int srcPortStart, int srcPortEnd, int destPortStart, int destPortEnd) throws ExecutionException { - manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp); - + int offset = 0; for (int srcPort = srcPortStart; srcPort <= srcPortEnd; srcPort++) { int destPort = destPortStart + offset; @@ -1220,7 +1220,6 @@ public class JuniperSrxResource implements ServerResource { private void removeDestinationNatRule(Long publicVlanTag, String publicIp, String privateIp, int srcPort, int destPort) throws ExecutionException { manageDestinationNatRule(SrxCommand.DELETE, publicIp, privateIp, srcPort, destPort); manageDestinationNatPool(SrxCommand.DELETE, privateIp, destPort); - manageProxyArp(SrxCommand.DELETE, publicVlanTag, publicIp); removeSecurityPolicyAndApplications(SecurityPolicyType.DESTINATION_NAT, privateIp); diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java index 4a90a77f428..9d24e478fe2 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -550,7 +550,9 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl ruleTO = new FirewallRuleTO(rule, guestVlanTag, rule.getTrafficType()); } else { IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); - ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr()); + Vlan vlan = _vlanDao.findById(sourceIp.getVlanId()); + + ruleTO = new FirewallRuleTO(rule, vlan.getVlanTag(), sourceIp.getAddress().addr()); } rulesTO.add(ruleTO); } diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index 37dcef382aa..8c094c85088 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -61,6 +61,8 @@ public class NetUtils { public final static String ALL_PROTO = "all"; public final static String ALL_CIDRS = "0.0.0.0/0"; + public final static int PORT_RANGE_MIN = 0; + public final static int PORT_RANGE_MAX = 65535; public final static int DEFAULT_AUTOSCALE_VM_DESTROY_TIME = 2 * 60; // Grace period before Vm is destroyed public final static int DEFAULT_AUTOSCALE_POLICY_INTERVAL_TIME = 30; From 51cf797d5ef69060c95dcb0fce47b2d96f16e26e Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Thu, 23 May 2013 22:57:13 -0700 Subject: [PATCH 107/201] CLOUDSTACK-2659 Advanced Zone - during VM deployment need to check network permissions for shared account-specific guest networks too Changes: - Check network permissions for account specific shared networks as well - Changes to error to include network uuid instead of id --- server/src/com/cloud/network/NetworkModelImpl.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 8971f8c163b..010cb9d5c54 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -32,6 +32,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -1488,24 +1489,25 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { @Override public void checkNetworkPermissions(Account owner, Network network) { // Perform account permission check - if (network.getGuestType() != Network.GuestType.Shared) { + if (network.getGuestType() != Network.GuestType.Shared + || (network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Account)) { AccountVO networkOwner = _accountDao.findById(network.getAccountId()); if(networkOwner == null) - throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", network does not have an owner"); + throw new PermissionDeniedException("Unable to use network with id= " + ((network != null)? ((NetworkVO)network).getUuid() : "") + ", network does not have an owner"); if(owner.getType() != Account.ACCOUNT_TYPE_PROJECT && networkOwner.getType() == Account.ACCOUNT_TYPE_PROJECT){ if(!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())){ - throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + throw new PermissionDeniedException("Unable to use network with id= " + ((network != null)? ((NetworkVO)network).getUuid() : "") + ", permission denied"); } }else{ List networkMap = _networksDao.listBy(owner.getId(), network.getId()); if (networkMap == null || networkMap.isEmpty()) { - throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + throw new PermissionDeniedException("Unable to use network with id= " + ((network != null)? ((NetworkVO)network).getUuid() : "") + ", permission denied"); } } } else { if (!isNetworkAvailableInDomain(network.getId(), owner.getDomainId())) { - throw new PermissionDeniedException("Shared network id=" + network.getUuid() + " is not available in domain id=" + owner.getDomainId()); + throw new PermissionDeniedException("Shared network id=" + ((network != null)? ((NetworkVO)network).getUuid() : "") + " is not available in domain id=" + owner.getDomainId()); } } } From 3e02a76f001b14ad25e5fdc55efc137457e5e52b Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Fri, 24 May 2013 11:09:33 +0530 Subject: [PATCH 108/201] CLOUDSTACK-528: Config value has to be encrypted for Hidden category configs --- .../com/cloud/upgrade/dao/Upgrade302to40.java | 41 +++++++++++++++++++ setup/db/db/schema-302to40.sql | 3 -- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java index ecda872dfa4..6f31fdd2b8e 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java @@ -18,6 +18,7 @@ package com.cloud.upgrade.dao; import java.io.File; +import java.io.UnsupportedEncodingException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -72,6 +73,7 @@ public class Upgrade302to40 extends Upgrade30xBase implements DbUpgrade { fixForeignKeys(conn); setupExternalNetworkDevices(conn); fixZoneUsingExternalDevices(conn); + encryptConfig(conn); } @Override @@ -1079,4 +1081,43 @@ public class Upgrade302to40 extends Upgrade30xBase implements DbUpgrade { s_logger.info("Successfully upgraded networks using F5 and SRX devices to have a entry in the network_external_lb_device_map and network_external_firewall_device_map"); } } + + private void encryptConfig(Connection conn){ + //Encrypt config params and change category to Hidden + s_logger.debug("Encrypting Config values"); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + pstmt = conn.prepareStatement("select name, value from `cloud`.`configuration` where name in ('router.ram.size', 'secondary.storage.vm', 'security.hash.key') and category <> 'Hidden'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + String name = rs.getString(1); + String value = rs.getString(2); + if (value == null) { + continue; + } + String encryptedValue = DBEncryptionUtil.encrypt(value); + pstmt = conn.prepareStatement("update `cloud`.`configuration` set value=?, category = 'Hidden' where name=?"); + pstmt.setBytes(1, encryptedValue.getBytes("UTF-8")); + pstmt.setString(2, name); + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable encrypt configuration values ", e); + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("Unable encrypt configuration values ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + s_logger.debug("Done encrypting Config values"); + } } diff --git a/setup/db/db/schema-302to40.sql b/setup/db/db/schema-302to40.sql index 7fa73483db6..832228cb434 100644 --- a/setup/db/db/schema-302to40.sql +++ b/setup/db/db/schema-302to40.sql @@ -114,9 +114,6 @@ UPDATE `cloud`.`configuration` set component='NetworkManager' where name='router UPDATE `cloud`.`configuration` set component='NetworkManager' where name='router.template.id'; UPDATE `cloud`.`configuration` set category='Advanced' where name='capacity.skipcounting.hours'; UPDATE `cloud`.`configuration` set category='Advanced' where name='use.local.storage'; -UPDATE `cloud`.`configuration` set category='Hidden' where name='router.ram.size'; -UPDATE `cloud`.`configuration` set category='Hidden' where name='secondary.storage.vm'; -UPDATE `cloud`.`configuration` set category='Hidden' where name='security.hash.key'; UPDATE `cloud`.`configuration` set description = 'Percentage (as a value between 0 and 1) of local storage utilization above which alerts will be sent about low local storage available.' where name = 'cluster.localStorage.capacity.notificationthreshold'; DELETE FROM `cloud`.`configuration` WHERE name='direct.agent.pool.size'; From 3b48299a0395916ad3dc8a95b6d98afd96ecf251 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Fri, 24 May 2013 12:37:09 +0530 Subject: [PATCH 109/201] CLOUDSTACK-2664: Fixed delete query. Added log message when CloudRuntimeException is thrown during upgrade --- .../schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java | 5 ++++- engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java index 9bc0ba599c2..e23815b7d28 100755 --- a/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -261,7 +261,10 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { } txn.commit(); - } finally { + } catch (CloudRuntimeException e){ + s_logger.error("Unable to upgrade the database", e); + throw new CloudRuntimeException("Unable to upgrade the database", e); + }finally { txn.close(); } } diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 95abe5f161e..f28d49687ea 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -759,7 +759,7 @@ public class Upgrade410to420 implements DbUpgrade { while (rs.next()) { long id = rs.getLong(1); // remove Firewall service for SG shared network offering - pstmt = conn.prepareStatement("DELETE `cloud`.`ntwk_offering_service_map` where network_offering_id=? and service='Firewall'"); + pstmt = conn.prepareStatement("DELETE from `cloud`.`ntwk_offering_service_map` where network_offering_id=? and service='Firewall'"); pstmt.setLong(1, id); pstmt.executeUpdate(); } From b2be0dbf6b48aa1d7a7e9cc7b5ab92dac84516b0 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 24 May 2013 11:12:39 +0530 Subject: [PATCH 110/201] Fixing incorrect ipaddress references test_network: references to ipaddress are ipaddress.ipaddress Added more logging to volume tests Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_network.py | 34 ++++++++++++-------------- test/integration/smoke/test_volumes.py | 2 +- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 61ddf46e9ef..9dfdc6e59d2 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -971,12 +971,12 @@ class TestLoadBalancingRule(cloudstackTestCase): try: self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % ( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id, self.vm_2.id )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, self.vm_1.password @@ -990,12 +990,12 @@ class TestLoadBalancingRule(cloudstackTestCase): self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % ( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id, self.vm_2.id )) ssh_2 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, self.vm_1.password @@ -1019,11 +1019,11 @@ class TestLoadBalancingRule(cloudstackTestCase): self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % ( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.vm_2.id )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, self.vm_1.password @@ -1033,7 +1033,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.debug("Hostnames after removing VM2: %s" % str(hostnames)) except Exception as e: self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, self.non_src_nat_ip.ipaddress)) + (e, self.non_src_nat_ip.ipaddress.ipaddress)) self.assertIn( self.vm_1.name, @@ -1045,11 +1045,11 @@ class TestLoadBalancingRule(cloudstackTestCase): with self.assertRaises(Exception): self.fail("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % ( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, + self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, self.vm_1.password @@ -1203,7 +1203,7 @@ class TestRebootRouter(cloudstackTestCase): self.debug("SSH into VM (ID : %s ) after reboot" % self.vm_1.id) remoteSSHClient( - self.nat_rule.ipaddress, + self.nat_rule.ipaddress.ipaddress, self.services["natrule"]["publicport"], self.vm_1.username, self.vm_1.password @@ -1211,8 +1211,7 @@ class TestRebootRouter(cloudstackTestCase): except Exception as e: self.fail( "SSH Access failed for %s: %s" % \ - (self.vm_1.ipaddress, e) - ) + (self.vm_1.ipaddress, e)) return def tearDown(self): @@ -1579,7 +1578,6 @@ class TestReleaseIP(cloudstackTestCase): "Check if disassociated IP Address is no longer available" ) - self.debug("List NAT Rule response" + str(list_nat_rule)) # ListPortForwardingRules should not list # associated rules with Public IP address try: @@ -1587,18 +1585,18 @@ class TestReleaseIP(cloudstackTestCase): self.apiclient, id=self.nat_rule.id ) + self.debug("List NAT Rule response" + str(list_nat_rule)) except cloudstackAPIException: self.debug("Port Forwarding Rule is deleted") # listLoadBalancerRules should not list # associated rules with Public IP address - self.debug("List LB Rule response" + str(list_lb_rule)) try: list_lb_rule = list_lb_rules( self.apiclient, id=self.lb_rule.id ) - + self.debug("List LB Rule response" + str(list_lb_rule)) except cloudstackAPIException: self.debug("Port Forwarding Rule is deleted") @@ -1658,7 +1656,6 @@ class TestDeleteAccount(cloudstackTestCase): try: src_nat_ip_addr = src_nat_ip_addrs[0] - except Exception as e: self.fail("SSH failed for VM with IP: %s" % src_nat_ip_addr.ipaddress) @@ -1740,10 +1737,9 @@ class TestDeleteAccount(cloudstackTestCase): "Check routers are properly deleted." ) except Exception as e: - raise Exception( - "Exception raised while fetching routers for account: %s" % - self.account.name) + "Encountered %s raised while fetching routers for account: %s" % (e, + self.account.name)) return def tearDown(self): diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 89b013a516f..7987136f88e 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -209,8 +209,8 @@ class TestCreateVolume(cloudstackTestCase): ) try: ssh = self.virtual_machine.get_ssh_client() + self.debug("Rebooting VM %s" % self.virtual_machine.id) ssh.execute("reboot") - except Exception as e: self.fail("SSH access failed for VM %s - %s" % (self.virtual_machine.ipaddress, e)) From a6d13cb7994e99203f99113ae901d110af8ba417 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 24 May 2013 14:22:47 +0530 Subject: [PATCH 111/201] Unwrap the test docstring for the testrunner Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_network.py | 222 ++++++++++++------------- 1 file changed, 110 insertions(+), 112 deletions(-) diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 9dfdc6e59d2..eb33c630ccf 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -189,8 +189,7 @@ class TestPublicIP(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke"]) def test_public_ip_admin_account(self): - """Test for Associate/Disassociate - public IP address for admin account""" + """Test for Associate/Disassociate public IP address for admin account""" # Validate the following: # 1. listPubliIpAddresses API returns the list of acquired addresses @@ -240,8 +239,7 @@ class TestPublicIP(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke"]) def test_public_ip_user_account(self): - """Test for Associate/Disassociate - public IP address for user account""" + """Test for Associate/Disassociate public IP address for user account""" # Validate the following: # 1. listPubliIpAddresses API returns the list of acquired addresses @@ -885,102 +883,102 @@ class TestLoadBalancingRule(cloudstackTestCase): # Check if VM is in Running state before creating LB rule vm_response = VirtualMachine.list( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) + self.apiclient, + account=self.account.name, + domainid=self.account.domainid + ) self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM returns a valid list" - ) + isinstance(vm_response, list), + True, + "Check list VM returns a valid list" + ) self.assertNotEqual( - len(vm_response), - 0, - "Check Port Forwarding Rule is created" - ) + len(vm_response), + 0, + "Check Port Forwarding Rule is created" + ) for vm in vm_response: self.assertEqual( - vm.state, - 'Running', - "VM state should be Running before creating a NAT rule." - ) + vm.state, + 'Running', + "VM state should be Running before creating a NAT rule." + ) #Create Load Balancer rule and assign VMs to rule lb_rule = LoadBalancerRule.create( - self.apiclient, - self.services["lbrule"], - self.non_src_nat_ip.ipaddress.id, - accountid=self.account.name - ) + self.apiclient, + self.services["lbrule"], + self.non_src_nat_ip.ipaddress.id, + accountid=self.account.name + ) self.cleanup.append(lb_rule) lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) lb_rules = list_lb_rules( - self.apiclient, - id=lb_rule.id - ) + self.apiclient, + id=lb_rule.id + ) self.assertEqual( - isinstance(lb_rules, list), - True, - "Check list response returns a valid list" - ) + isinstance(lb_rules, list), + True, + "Check list response returns a valid list" + ) #verify listLoadBalancerRules lists the added load balancing rule self.assertNotEqual( - len(lb_rules), - 0, - "Check Load Balancer Rule in its List" - ) + len(lb_rules), + 0, + "Check Load Balancer Rule in its List" + ) self.assertEqual( - lb_rules[0].id, - lb_rule.id, - "Check List Load Balancer Rules returns valid Rule" - ) + lb_rules[0].id, + lb_rule.id, + "Check List Load Balancer Rules returns valid Rule" + ) # listLoadBalancerRuleInstances should list # all instances associated with that LB rule lb_instance_rules = list_lb_instances( - self.apiclient, - id=lb_rule.id - ) + self.apiclient, + id=lb_rule.id + ) self.assertEqual( - isinstance(lb_instance_rules, list), - True, - "Check list response returns a valid list" - ) + isinstance(lb_instance_rules, list), + True, + "Check list response returns a valid list" + ) self.assertNotEqual( - len(lb_instance_rules), - 0, - "Check Load Balancer instances Rule in its List" - ) + len(lb_instance_rules), + 0, + "Check Load Balancer instances Rule in its List" + ) self.assertIn( - lb_instance_rules[0].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) + lb_instance_rules[0].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) self.assertIn( - lb_instance_rules[1].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) + lb_instance_rules[1].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) try: self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % - ( - self.non_src_nat_ip.ipaddress.ipaddress, - self.vm_1.id, - self.vm_2.id - )) + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id, + self.vm_2.id + )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) # If Round Robin Algorithm is chosen, # each ssh command should alternate between VMs @@ -989,71 +987,71 @@ class TestLoadBalancingRule(cloudstackTestCase): time.sleep(self.services["lb_switch_wait"]) self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % - ( - self.non_src_nat_ip.ipaddress.ipaddress, - self.vm_1.id, - self.vm_2.id - )) + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id, + self.vm_2.id + )) ssh_2 = remoteSSHClient( - self.non_src_nat_ip.ipaddress.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) hostnames.append(ssh_2.execute("hostname")[0]) self.debug("Hostnames after adding 2 VMs to LB rule: %s" % str(hostnames)) self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) self.assertIn( - self.vm_2.name, - hostnames, - "Check if ssh succeeded for server2" - ) + self.vm_2.name, + hostnames, + "Check if ssh succeeded for server2" + ) #SSH should pass till there is a last VM associated with LB rule lb_rule.remove(self.apiclient, [self.vm_2]) self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % - ( - self.non_src_nat_ip.ipaddress.ipaddress, - self.vm_2.id - )) + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_2.id + )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) hostnames.append(ssh_1.execute("hostname")[0]) self.debug("Hostnames after removing VM2: %s" % str(hostnames)) except Exception as e: self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, self.non_src_nat_ip.ipaddress.ipaddress)) + (e, self.non_src_nat_ip.ipaddress.ipaddress)) self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) lb_rule.remove(self.apiclient, [self.vm_1]) with self.assertRaises(Exception): - self.fail("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % - ( - self.non_src_nat_ip.ipaddress.ipaddress, - self.vm_1.id - )) + self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id + )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) ssh_1.execute("hostname")[0] return @@ -1556,7 +1554,7 @@ class TestReleaseIP(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke"]) def test_releaseIP(self): - """Test for Associate/Disassociate public IP address""" + """Test for release public IP address""" self.debug("Deleting Public IP : %s" % self.ip_addr.id) From 09c6030ae9fd759b59634a10e98eb2698a848539 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 24 May 2013 14:23:14 +0530 Subject: [PATCH 112/201] Correct the resize volume tests Resize would fail on XenServer if the VM isn't stopped before resizing. Ensuring VM stop based on the hypervisor host detected that the VM is resident on. Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_volumes.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 7987136f88e..d9c808a01d9 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -536,7 +536,7 @@ class TestVolumes(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_07_resize_fail(self): - """Verify invalid options fail to Resize a volume""" + """Test resize (negative) non-existent volume""" # Verify the size is the new size is what we wanted it to be. self.debug("Fail Resize Volume ID: %s" % self.volume.id) @@ -584,7 +584,12 @@ class TestVolumes(cloudstackTestCase): self.virtual_machine.attach_volume(self.apiClient, self.volume) self.attached = True #stop the vm if it is on xenserver - if self.services['hypervisor'].lower() == "xenserver": + hosts = Host.list(self.apiClient, id=self.virtual_machine.hostid) + self.assertTrue(isinstance(hosts, list)) + self.assertTrue(len(hosts) > 0) + self.debug("Found %s host" % hosts[0].hypervisor) + + if hosts[0].hypervisor == "XenServer": self.virtual_machine.stop(self.apiClient) self.apiClient.resizeVolume(cmd) @@ -610,23 +615,28 @@ class TestVolumes(cloudstackTestCase): True, "Verify the volume did not resize" ) - if self.services['hypervisor'].lower() == "xenserver": + if hosts[0].hypervisor == "XenServer": self.virtual_machine.start(self.apiClient) @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_08_resize_volume(self): - """Resize a volume""" + """Test resize a volume""" # Verify the size is the new size is what we wanted it to be. self.debug( "Attaching volume (ID: %s) to VM (ID: %s)" % ( self.volume.id, self.virtual_machine.id )) + self.virtual_machine.attach_volume(self.apiClient, self.volume) self.attached = True + hosts = Host.list(self.apiClient, id=self.virtual_machine.hostid) + self.assertTrue(isinstance(hosts, list)) + self.assertTrue(len(hosts) > 0) + self.debug("Found %s host" % hosts[0].hypervisor) - if self.services['hypervisor'].lower() == "xenserver": + if hosts[0].hypervisor == "XenServer": self.virtual_machine.stop(self.apiClient) self.debug("Resize Volume ID: %s" % self.volume.id) @@ -659,7 +669,9 @@ class TestVolumes(cloudstackTestCase): "Check if the volume resized appropriately" ) - if self.services['hypervisor'].lower() == "xenserver": + #start the vm if it is on xenserver + + if hosts[0].hypervisor == "XenServer": self.virtual_machine.start(self.apiClient) @attr(tags = ["advanced", "advancedns", "smoke","basic"]) From 47a562a2c043c32fdf1f3108552cfce170b8b27e Mon Sep 17 00:00:00 2001 From: Bharat Kumar Date: Tue, 21 May 2013 12:21:01 +0530 Subject: [PATCH 113/201] Cloudstack-2548: Failed to delete public IP range Public IP range deletion after it is dedicated fails with IP range being used for DHCP offers. Signed-off-by: Prasanna Santhanam --- .../cloud/configuration/ConfigurationManagerImpl.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 47c54822adb..214e292963f 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -3071,9 +3071,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } + } else { + // when there is no dhcp support in the network. + if (!deletePublicIPRange(vlanDbId)) { + return false; + } + _vlanDao.expunge(vlanDbId); + return true; } } - throw new InvalidParameterValueException("One of the ips in the range is used to provide Dhcp service to this subnet. cannot delete this range as "); + return false; } From a23f151df57a16457587207e612b3f26911806e6 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Fri, 24 May 2013 14:41:17 +0530 Subject: [PATCH 114/201] KVM snapshots backUp path in 22 had entire path, instead of relative path. Fix modifies the path to make it relative during upgrade --- .../cloud/upgrade/dao/Upgrade410to420.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index f28d49687ea..e7f47331eab 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -76,6 +76,7 @@ public class Upgrade410to420 implements DbUpgrade { addHostDetailsIndex(conn); updateNetworksForPrivateGateways(conn); removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); + fix22xKVMSnapshots(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -779,4 +780,43 @@ public class Upgrade410to420 implements DbUpgrade { } } + private void fix22xKVMSnapshots(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + s_logger.debug("Updating KVM snapshots"); + try { + pstmt = conn.prepareStatement("select id, backup_snap_id from `cloud`.`snapshots` where hypervisor_type='KVM' and removed is null and backup_snap_id is not null"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + String backUpPath = rs.getString(2); + // Update Backup Path. Remove anything before /snapshots/ + // e.g 22x Path /mnt/0f14da63-7033-3ca5-bdbe-fa62f4e2f38a/snapshots/1/2/6/i-2-6-VM_ROOT-6_20121219072022 + // Above path should change to /snapshots/1/2/6/i-2-6-VM_ROOT-6_20121219072022 + int index = backUpPath.indexOf("snapshots"+File.separator); + if (index > 1){ + String correctedPath = File.separator + backUpPath.substring(index); + s_logger.debug("Updating Snapshot with id: "+id+" original backup path: "+backUpPath+ " updated backup path: "+correctedPath); + pstmt = conn.prepareStatement("UPDATE `cloud`.`snapshots` set backup_snap_id=? where id = ?"); + pstmt.setString(1, correctedPath); + pstmt.setLong(2, id); + pstmt.executeUpdate(); + } + } + s_logger.debug("Done updating KVM snapshots"); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to update backup id for KVM snapshots", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } } From 6e1103e9240388332a2d39cf39a4afd30f02cc4e Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 24 May 2013 14:43:59 +0530 Subject: [PATCH 115/201] Removing tests that were written in the old design The APIs addVolumeDetail and addNicDetail do not exist. These were part of the old resource tagging design. Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_nicdetail.py | 224 ------------------ test/integration/smoke/test_volumedetail.py | 239 -------------------- 2 files changed, 463 deletions(-) delete mode 100644 test/integration/smoke/test_nicdetail.py delete mode 100644 test/integration/smoke/test_volumedetail.py diff --git a/test/integration/smoke/test_nicdetail.py b/test/integration/smoke/test_nicdetail.py deleted file mode 100644 index 3d8b1d62a47..00000000000 --- a/test/integration/smoke/test_nicdetail.py +++ /dev/null @@ -1,224 +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. -""" P1 tests for Scaling up Vm -""" -#Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.remoteSSHClient import remoteSSHClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -from nose.plugins.attrib import attr -#Import System modules -import time - -_multiprocess_shared_ = True -class Services: - """Test VM Life Cycle Services - """ - - def __init__(self): - self.services = { - - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended in create account to - # ensure unique username generated each time - "password": "password", - }, - "small": - # Create a small virtual machine instance with disk offering - { - "displayname": "testserver", - "username": "root", # VM creds for SSH - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "storagetype": "shared", - "disksize": 1 - }, - "service_offerings": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "diskdevice": '/dev/xvdd', - # Disk device where ISO is attached to instance - "mount_dir": "/mnt/tmp", - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', - # CentOS 5.3 (64-bit) - } - -class TestNicDetail(cloudstackTestCase): - - @classmethod - def setUpClass(cls): - cls.api_client = super(TestNicDetail, cls).getClsTestClient().getApiClient() - cls.services = Services().services - - # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = zone.networktype - - # Set Zone - - # Create account, service offerings, vm. - cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=domain.id - ) - - cls.nic = "163738c7-ce3a-481d-ac68-4a8337043415"; - #how does it work - cls._cleanup = [ - cls.account - ] - - @classmethod - def tearDownClass(cls): - cls.api_client = super(TestNicDetail, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) - return - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.dbclient = self.testClient.getDbConnection() - self.cleanup = [] - - def tearDown(self): - #Clean up, terminate the created ISOs - cleanup_resources(self.apiclient, self.cleanup) - return - - @attr(tags = ["advanced", "xenserver"]) - def test_01_updatenicdetail(self): - """Test nic detail - """ - # Validate the following - # Scale up the vm and see if it scales to the new svc offering and is finally in running state - - self.debug("Testing ADD nic detail Nic-ID: %s " % ( - self.nic - )) - - cmd = addNicDetail.addNicDetailCmd() - cmd.name = self.nic - cmd.value = self.nic - cmd.id = self.nic - self.apiclient.addNicDetail(cmd) - - listNicDetailCmd = listNicDetails.listNicDetailsCmd() - listNicDetailCmd.id = self.nic - listNicDetailResponse = self.api_client.listVirtualMachines(listNicDetailCmd) - - self.assertNotEqual(len(listNicDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - nicdetail = listNicDetailResponse[0] - - #self.assertEqual(nicdetail.id, self.nic, "Check if the Nic returned is the same as the one we asked for") - - - self.assertEqual(nicdetail.name, self.nic, "Check if Nic has right name") - - self.assertEqual(nicdetail.value, self.nic, "Check if Nic has right value") - - #updatenicdetail - self.debug("Testing UPDATE nic detail Nic-ID: %s " % ( - self.nic - )) - cmd = updateNicDetail.updateNicDetailCmd() - cmd.name = self.nic - cmd.value = self.disk_offering.id - cmd.id = self.nic - self.apiclient.addNicDetail(cmd) - - listNicDetailCmd = listNicDetails.listNicDetailsCmd() - listNicDetailCmd.id = self.nic - listNicDetailResponse = self.api_client.listVirtualMachines(listNicDetailCmd) - - self.assertNotEqual(len(listNicDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - nicdetail = listNicDetailResponse[0] - - #self.assertEqual(nicdetail.id, self.nic, "Check if the Nic returned is the same as the one we asked for") - - - self.assertEqual(nicdetail.name, self.nic, "Check if Nic has right name") - - self.assertEqual(nicdetail.value, self.disk_offering.id, "Check if Nic has right value") - - - #remove detail - self.debug("Testing REMOVE nic detail Nic-ID: %s " % ( - self.nic - )) - cmd = removeNicDetail.removeNicDetailCmd() - cmd.name = self.nic - cmd.id = self.nic - self.apiclient.removeNicDetail(cmd) - - listNicDetailCmd = listNicDetails.listNicDetailsCmd() - listNicDetailCmd.id = self.nic - listNicDetailResponse = self.api_client.listVirtualMachines(listNicDetailCmd) - - self.assertEqual(listNicDetailResponse, None, "Check if the list API \ - returns a non-empty response") - - - return diff --git a/test/integration/smoke/test_volumedetail.py b/test/integration/smoke/test_volumedetail.py deleted file mode 100644 index f734dbb4de6..00000000000 --- a/test/integration/smoke/test_volumedetail.py +++ /dev/null @@ -1,239 +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. -""" P1 tests for Scaling up Vm -""" -#Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.remoteSSHClient import remoteSSHClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -from nose.plugins.attrib import attr -#Import System modules -import time - -_multiprocess_shared_ = True -class Services: - """Test VM Life Cycle Services - """ - - def __init__(self): - self.services = { - - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended in create account to - # ensure unique username generated each time - "password": "password", - }, - "small": - # Create a small virtual machine instance with disk offering - { - "displayname": "testserver", - "username": "root", # VM creds for SSH - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "storagetype": "shared", - "disksize": 1 - }, - "service_offerings": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "diskdevice": '/dev/xvdd', - # Disk device where ISO is attached to instance - "mount_dir": "/mnt/tmp", - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', - # CentOS 5.3 (64-bit) - } - -class TestVolumeDetail(cloudstackTestCase): - - @classmethod - def setUpClass(cls): - cls.api_client = super(TestVolumeDetail, cls).getClsTestClient().getApiClient() - cls.services = Services().services - - # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = zone.networktype - - # Set Zones and disk offerings ?? - - # Create account, service offerings, vm. - cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=domain.id - ) - - - cls.disk_offering = DiskOffering.create( - cls.api_client, - cls.services["disk_offering"] - ) - - #create a volume - cls.volume = Volume.create( - cls.api_client, - { "diskname" : "ndm"}, - zoneid=zone.id, - account=cls.account.name, - domainid=cls.account.domainid, - diskofferingid=cls.disk_offering.id - ) - #how does it work ?? - cls._cleanup = [ - cls.volume, - cls.account - ] - - @classmethod - def tearDownClass(cls): - cls.api_client = super(TestVolumeDetail, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) - return - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.dbclient = self.testClient.getDbConnection() - self.cleanup = [] - - def tearDown(self): - #Clean up, terminate the created ISOs - cleanup_resources(self.apiclient, self.cleanup) - return - - @attr(tags = ["advanced", "xenserver"]) - def test_01_updatevolumedetail(self): - """Test volume detail - """ - # Validate the following - # Scale up the vm and see if it scales to the new svc offering and is finally in running state - - self.debug("Testing ADD volume detail Volume-ID: %s " % ( - self.volume.id - )) - - cmd = addVolumeDetail.addVolumeDetailCmd() - cmd.name = self.volume.id - cmd.value = self.volume.id - cmd.id = self.volume.id - self.apiclient.addVolumeDetail(cmd) - - listVolumeDetailCmd = listVolumeDetails.listVolumeDetailsCmd() - listVolumeDetailCmd.id = self.volume.id - listVolumeDetailResponse = self.api_client.listVirtualMachines(listVolumeDetailCmd) - - self.assertNotEqual(len(listVolumeDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - volumedetail = listVolumeDetailResponse[0] - - #self.assertEqual(volumedetail.id, self.volume.id, "Check if the Volume returned is the same as the one we asked for") - - - self.assertEqual(volumedetail.name, self.volume.id, "Check if Volume has right name") - - self.assertEqual(volumedetail.value, self.volume.id, "Check if Volume has right value") - - #updatevolumedetail - self.debug("Testing UPDATE volume detail Volume-ID: %s " % ( - self.volume.id - )) - cmd = updateVolumeDetail.updateVolumeDetailCmd() - cmd.name = self.volume.id - cmd.value = self.disk_offering.id - cmd.id = self.volume.id - self.apiclient.addVolumeDetail(cmd) - - listVolumeDetailCmd = listVolumeDetails.listVolumeDetailsCmd() - listVolumeDetailCmd.id = self.volume.id - listVolumeDetailResponse = self.api_client.listVirtualMachines(listVolumeDetailCmd) - - self.assertNotEqual(len(listVolumeDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - volumedetail = listVolumeDetailResponse[0] - - #self.assertEqual(volumedetail.id, self.volume.id, "Check if the Volume returned is the same as the one we asked for") - - - self.assertEqual(volumedetail.name, self.volume.id, "Check if Volume has right name") - - self.assertEqual(volumedetail.value, self.disk_offering.id, "Check if Volume has right value") - - - #remove detail - self.debug("Testing REMOVE volume detail Volume-ID: %s " % ( - self.volume.id - )) - cmd = removeVolumeDetail.removeVolumeDetailCmd() - cmd.name = self.volume.id - cmd.id = self.volume.id - self.apiclient.removeVolumeDetail(cmd) - - listVolumeDetailCmd = listVolumeDetails.listVolumeDetailsCmd() - listVolumeDetailCmd.id = self.volume.id - listVolumeDetailResponse = self.api_client.listVirtualMachines(listVolumeDetailCmd) - - self.assertEqual(listVolumeDetailResponse, None, "Check if the list API \ - returns a non-empty response") - - - return From ba67e5d56ed9e960e947925f82d2dda2204389ce Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Fri, 24 May 2013 16:00:39 +0530 Subject: [PATCH 116/201] CLOUDSTACK-2452: Fixed account upgrade for usage. Added cloumn default. Updated usage response for PF , LB and VPN to return UUID instead of Id --- .../src/com/cloud/api/ApiResponseHelper.java | 297 +++++++++--------- setup/db/db/schema-410to420.sql | 2 + 2 files changed, 153 insertions(+), 146 deletions(-) diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 540c8e9a4d7..89739cfde22 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -34,6 +34,30 @@ import java.util.TimeZone; import javax.inject.Inject; +import com.cloud.network.GuestVlan; +import com.cloud.network.IpAddress; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; +import com.cloud.network.NetworkProfile; +import com.cloud.network.PhysicalNetwork; +import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.PhysicalNetworkTrafficType; +import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.Site2SiteCustomerGateway; +import com.cloud.network.Site2SiteVpnConnection; +import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.VirtualRouterProvider; +import com.cloud.network.VpnUser; +import com.cloud.network.VpnUserVO; +import com.cloud.network.dao.LoadBalancerVO; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.PortForwardingRuleVO; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.network.rules.StickinessPolicy; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -193,25 +217,11 @@ import com.cloud.event.Event; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.hypervisor.HypervisorCapabilities; -import com.cloud.network.GuestVlan; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkModel; -import com.cloud.network.NetworkProfile; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.Site2SiteCustomerGateway; -import com.cloud.network.Site2SiteVpnConnection; -import com.cloud.network.Site2SiteVpnGateway; -import com.cloud.network.VirtualRouterProvider; -import com.cloud.network.VpnUser; import com.cloud.network.as.AutoScalePolicy; import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.network.as.AutoScaleVmProfile; @@ -223,14 +233,7 @@ import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.router.VirtualRouter; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.HealthCheckPolicy; -import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.LoadBalancerContainer.Scheme; -import com.cloud.network.rules.PortForwardingRule; -import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.rules.StickinessPolicy; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; @@ -3452,147 +3455,149 @@ public class ApiResponseHelper implements ResponseGenerator { } - @Override - public UsageRecordResponse createUsageResponse(Usage usageRecord) { - UsageRecordResponse usageRecResponse = new UsageRecordResponse(); + @Override + public UsageRecordResponse createUsageResponse(Usage usageRecord) { + UsageRecordResponse usageRecResponse = new UsageRecordResponse(); - Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()); - if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - //find the project - Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId()); - usageRecResponse.setProjectId(project.getUuid()); - usageRecResponse.setProjectName(project.getName()); - } else { - usageRecResponse.setAccountId(account.getUuid()); - usageRecResponse.setAccountName(account.getAccountName()); - } + Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()); + if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { + //find the project + Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId()); + usageRecResponse.setProjectId(project.getUuid()); + usageRecResponse.setProjectName(project.getName()); + } else { + usageRecResponse.setAccountId(account.getUuid()); + usageRecResponse.setAccountName(account.getAccountName()); + } - Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); - if (domain != null) { - usageRecResponse.setDomainId(domain.getUuid()); - } + Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); + if (domain != null) { + usageRecResponse.setDomainId(domain.getUuid()); + } - if (usageRecord.getZoneId() != null) { - DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); - if (zone != null) { - usageRecResponse.setZoneId(zone.getUuid()); - } - } - usageRecResponse.setDescription(usageRecord.getDescription()); - usageRecResponse.setUsage(usageRecord.getUsageDisplay()); - usageRecResponse.setUsageType(usageRecord.getUsageType()); - if (usageRecord.getVmInstanceId() != null) { - VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId()); - usageRecResponse.setVirtualMachineId(vm.getUuid()); - } - usageRecResponse.setVmName(usageRecord.getVmName()); - if (usageRecord.getTemplateId() != null) { - VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId()); - if (template != null) { - usageRecResponse.setTemplateId(template.getUuid()); - } - } + if (usageRecord.getZoneId() != null) { + DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); + if (zone != null) { + usageRecResponse.setZoneId(zone.getUuid()); + } + } + usageRecResponse.setDescription(usageRecord.getDescription()); + usageRecResponse.setUsage(usageRecord.getUsageDisplay()); + usageRecResponse.setUsageType(usageRecord.getUsageType()); + if (usageRecord.getVmInstanceId() != null) { + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId()); + usageRecResponse.setVirtualMachineId(vm.getUuid()); + } + usageRecResponse.setVmName(usageRecord.getVmName()); + if (usageRecord.getTemplateId() != null) { + VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId()); + if (template != null) { + usageRecResponse.setTemplateId(template.getUuid()); + } + } - if(usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM){ - ServiceOfferingVO svcOffering = _entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, usageRecord.getOfferingId().toString()); - //Service Offering Id - usageRecResponse.setOfferingId(svcOffering.getUuid()); - //VM Instance ID - VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(vm.getUuid()); - //Hypervisor Type - usageRecResponse.setType(usageRecord.getType()); + if(usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM){ + ServiceOfferingVO svcOffering = _entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, usageRecord.getOfferingId().toString()); + //Service Offering Id + usageRecResponse.setOfferingId(svcOffering.getUuid()); + //VM Instance ID + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vm.getUuid()); + //Hypervisor Type + usageRecResponse.setType(usageRecord.getType()); - } else if(usageRecord.getUsageType() == UsageTypes.IP_ADDRESS){ - //isSourceNAT - usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat"))?true:false); - //isSystem - usageRecResponse.setSystem((usageRecord.getSize() == 1)?true:false); - //IP Address ID - IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(ip.getUuid()); + } else if(usageRecord.getUsageType() == UsageTypes.IP_ADDRESS){ + //isSourceNAT + usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat"))?true:false); + //isSystem + usageRecResponse.setSystem((usageRecord.getSize() == 1)?true:false); + //IP Address ID + IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(ip.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED){ - //Device Type - usageRecResponse.setType(usageRecord.getType()); - if(usageRecord.getType().equals("DomainRouter")){ - //Domain Router Id - VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(vm.getUuid()); - } else { - //External Device Host Id - HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(host.getUuid()); - } - //Network ID - NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString()); - usageRecResponse.setNetworkId(network.getUuid()); + } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED){ + //Device Type + usageRecResponse.setType(usageRecord.getType()); + if(usageRecord.getType().equals("DomainRouter")){ + //Domain Router Id + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vm.getUuid()); + } else { + //External Device Host Id + HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(host.getUuid()); + } + //Network ID + NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString()); + usageRecResponse.setNetworkId(network.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.VOLUME){ - //Volume ID - VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(volume.getUuid()); - //Volume Size - usageRecResponse.setSize(usageRecord.getSize()); - //Disk Offering Id - if(usageRecord.getOfferingId() != null){ - DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); - usageRecResponse.setOfferingId(diskOff.getUuid()); - } + } else if(usageRecord.getUsageType() == UsageTypes.VOLUME){ + //Volume ID + VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(volume.getUuid()); + //Volume Size + usageRecResponse.setSize(usageRecord.getSize()); + //Disk Offering Id + if(usageRecord.getOfferingId() != null){ + DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); + usageRecResponse.setOfferingId(diskOff.getUuid()); + } - } else if(usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO){ - //Template/ISO ID - VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(tmpl.getUuid()); - //Template/ISO Size - usageRecResponse.setSize(usageRecord.getSize()); + } else if(usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO){ + //Template/ISO ID + VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(tmpl.getUuid()); + //Template/ISO Size + usageRecResponse.setSize(usageRecord.getSize()); - } else if(usageRecord.getUsageType() == UsageTypes.SNAPSHOT){ - //Snapshot ID - SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(snap.getUuid()); - //Snapshot Size - usageRecResponse.setSize(usageRecord.getSize()); + } else if(usageRecord.getUsageType() == UsageTypes.SNAPSHOT){ + //Snapshot ID + SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(snap.getUuid()); + //Snapshot Size + usageRecResponse.setSize(usageRecord.getSize()); - } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ - //Load Balancer Policy ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ + //Load Balancer Policy ID + LoadBalancerVO lb = _entityMgr.findByIdIncludingRemoved(LoadBalancerVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(lb.getUuid()); + } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ + //Port Forwarding Rule ID + PortForwardingRuleVO pf = _entityMgr.findByIdIncludingRemoved(PortForwardingRuleVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(pf.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ - //Port Forwarding Rule ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ + //Network Offering Id + NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); + usageRecResponse.setOfferingId(netOff.getUuid()); + //is Default + usageRecResponse.setDefault((usageRecord.getUsageId() == 1)? true:false); - } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ - //Network Offering Id - NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); - usageRecResponse.setOfferingId(netOff.getUuid()); - //is Default - usageRecResponse.setDefault((usageRecord.getUsageId() == 1)? true:false); + } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ + //VPN User ID + VpnUserVO vpnUser = _entityMgr.findByIdIncludingRemoved(VpnUserVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vpnUser.getUuid()); - } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ - //VPN User ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ + //Security Group Id + SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(sg.getUuid()); + } - } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ - //Security Group Id - SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(sg.getUuid()); - } + if (usageRecord.getRawUsage() != null) { + DecimalFormat decimalFormat = new DecimalFormat("###########.######"); + usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage())); + } - if (usageRecord.getRawUsage() != null) { - DecimalFormat decimalFormat = new DecimalFormat("###########.######"); - usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage())); - } + if (usageRecord.getStartDate() != null) { + usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); + } + if (usageRecord.getEndDate() != null) { + usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); + } - if (usageRecord.getStartDate() != null) { - usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); - } - if (usageRecord.getEndDate() != null) { - usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); - } - - return usageRecResponse; - } + return usageRecResponse; + } public String getDateStringInternal(Date inputDate) { diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 885eff46132..435bb83d3c9 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1040,8 +1040,10 @@ CREATE VIEW `cloud`.`service_offering_view` AS -- Add "default" field to account/user tables ALTER TABLE `cloud`.`account` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if account is default'; +ALTER TABLE `cloud_usage`.`account` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if account is default'; ALTER TABLE `cloud`.`user` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if user is default'; UPDATE `cloud`.`account` SET `cloud`.`account`.`default`=1 WHERE id IN (1,2); +UPDATE `cloud_usage`.`account` SET `default`=1 WHERE id IN (1,2); UPDATE `cloud`.`user` SET `cloud`.`user`.`default`=1 WHERE id IN (1,2); ALTER VIEW `cloud`.`user_view` AS From 23baacba62e6169aeeaeabb3441b393ee5491851 Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Fri, 24 May 2013 16:04:23 +0530 Subject: [PATCH 117/201] CLOUDSTACK-2669 - Adding resource limit and count logic for scale vm --- .../src/com/cloud/vm/UserVmManagerImpl.java | 50 ++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 5e206567bed..c10a9d8d595 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -819,6 +819,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } + @Override public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException { Long vmId = cmd.getVmId(); @@ -1112,21 +1113,47 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use //Check if its a scale "up" ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newServiceOfferingId); - ServiceOffering oldServiceOffering = _configMgr.getServiceOffering(vmInstance.getServiceOfferingId()); - if(newServiceOffering.getSpeed() <= oldServiceOffering.getSpeed() - && newServiceOffering.getRamSize() <= oldServiceOffering.getRamSize()){ + ServiceOffering currentServiceOffering = _configMgr.getServiceOffering(vmInstance.getServiceOfferingId()); + int newCpu = newServiceOffering.getCpu(); + int newMemory = newServiceOffering.getRamSize(); + int newSpeed = newServiceOffering.getSpeed(); + int currentCpu = currentServiceOffering.getCpu(); + int currentMemory = currentServiceOffering.getRamSize(); + int currentSpeed = currentServiceOffering.getSpeed(); + + if(newSpeed <= currentSpeed + && newMemory <= currentMemory + && newCpu <= currentCpu){ throw new InvalidParameterValueException("Only scaling up the vm is supported, new service offering should have both cpu and memory greater than the old values"); } + // Check resource limits + if (newCpu > currentCpu) { + _resourceLimitMgr.checkResourceLimit(caller, ResourceType.cpu, + newCpu - currentCpu); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.checkResourceLimit(caller, ResourceType.memory, + newMemory - currentMemory); + } + // Dynamically upgrade the running vms boolean success = false; if(vmInstance.getState().equals(State.Running)){ int retry = _scaleRetry; + // Increment CPU and Memory count accordingly. + if (newCpu > currentCpu) { + _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long (newMemory - currentMemory)); + } + while (retry-- != 0) { // It's != so that it can match -1. try{ // #1 Check existing host has capacity - boolean existingHostHasCapacity = _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), newServiceOffering.getSpeed() - oldServiceOffering.getSpeed(), - (newServiceOffering.getRamSize() - oldServiceOffering.getRamSize()) * 1024L * 1024L, false, ApiDBUtils.getCpuOverprovisioningFactor(), 1f, false); // TO DO fill it with mem. + boolean existingHostHasCapacity = _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), newServiceOffering.getSpeed() - currentServiceOffering.getSpeed(), + (newServiceOffering.getRamSize() - currentServiceOffering.getRamSize()) * 1024L * 1024L, false, ApiDBUtils.getCpuOverprovisioningFactor(), 1f, false); // TO DO fill it with mem. // #2 migrate the vm if host doesn't have capacity if (!existingHostHasCapacity){ @@ -1136,7 +1163,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // #3 scale the vm now _itMgr.upgradeVmDb(vmId, newServiceOfferingId); vmInstance = _vmInstanceDao.findById(vmId); - vmInstance = _itMgr.reConfigureVm(vmInstance, oldServiceOffering, existingHostHasCapacity); + vmInstance = _itMgr.reConfigureVm(vmInstance, currentServiceOffering, existingHostHasCapacity); success = true; return success; }catch(InsufficientCapacityException e ){ @@ -1151,8 +1178,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.warn("Received exception while scaling ",e); }finally{ if(!success){ - _itMgr.upgradeVmDb(vmId, oldServiceOffering.getId()); // rollback + _itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback + // Decrement CPU and Memory count accordingly. + if (newCpu > currentCpu) { + _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long (newMemory - currentMemory)); + } } + + } } } From a34e577d1be5a25d7eb884147212ab51786b55e2 Mon Sep 17 00:00:00 2001 From: Harikrishna Patnala Date: Fri, 24 May 2013 16:38:55 +0530 Subject: [PATCH 118/201] CLOUDSTACK-1453: support restore for VM created from ISO This is to support restore a vm to a new/currently_attached ISO. In the restorevm API we have an optional parameter templateId to restore the vm to the new template/ISO ID. --- .../api/command/user/vm/RestoreVMCmd.java | 5 ++- .../src/com/cloud/vm/UserVmManagerImpl.java | 43 ++++++++++++++----- .../test/com/cloud/vm/UserVmManagerTest.java | 42 ++++++++++++++++-- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java index 9c33f97c317..2f7d8e10a77 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.Account; import com.cloud.user.UserContext; import com.cloud.uservm.UserVm; -@APICommand(name = "restoreVirtualMachine", description="Restore a VM to original template or new template", responseObject=UserVmResponse.class, since="3.0.0") +@APICommand(name = "restoreVirtualMachine", description="Restore a VM to original template/ISO or new template/ISO", responseObject=UserVmResponse.class, since="3.0.0") public class RestoreVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RestoreVMCmd.class); private static final String s_name = "restorevmresponse"; @@ -44,9 +44,10 @@ public class RestoreVMCmd extends BaseAsyncCmd { required=true, description="Virtual Machine ID") private Long vmId; - @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.UUID, entityType = TemplateResponse.class, description="an optional template Id to restore vm from the new template") + @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.UUID, entityType = TemplateResponse.class, description="an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO") private Long templateId; + @Override public String getEventType() { return EventTypes.EVENT_VM_RESTORE; diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index c10a9d8d595..96b95293b47 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -4237,6 +4237,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use long vmId = cmd.getVmId(); Long newTemplateId = cmd.getTemplateId(); + UserVmVO vm = _vmDao.findById(vmId); if (vm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Cannot find VM with ID " + vmId); @@ -4292,21 +4293,35 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use VolumeVO root = rootVols.get(0); Long templateId = root.getTemplateId(); + boolean isISO = false; if(templateId == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("Currently there is no support to reset a vm that is deployed using ISO " + vm.getUuid()); - ex.addProxyObject(vm, vmId, "vmId"); - throw ex; + // Assuming that for a vm deployed using ISO, template ID is set to NULL + isISO = true; + templateId = vm.getIsoId(); } VMTemplateVO template = null; + //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly if(newTemplateId != null) { template = _templateDao.findById(newTemplateId); _accountMgr.checkAccess(caller, null, true, template); + if (isISO) { + if (!template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); + } + } else { + if (template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid template id provided to restore the VM "); + } + } } else { + if (isISO && templateId == null) { + throw new CloudRuntimeException("Cannot restore the VM since there is no ISO attached to VM"); + } template = _templateDao.findById(templateId); if (template == null) { InvalidParameterValueException ex = new InvalidParameterValueException( - "Cannot find template for specified volumeid and vmId"); + "Cannot find template/ISO for specified volumeid and vmId"); ex.addProxyObject(vm, vmId, "vmId"); ex.addProxyObject(root, root.getId(), "volumeId"); throw ex; @@ -4325,13 +4340,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - /* If new template is provided allocate a new volume from new template otherwise allocate new volume from original template */ + /* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */ VolumeVO newVol = null; - if (newTemplateId != null){ - newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); - vm.setGuestOSId(template.getGuestOSId()); - vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); + if (newTemplateId != null) { + if (isISO) { + newVol = volumeMgr.allocateDuplicateVolume(root, null); + vm.setIsoId(newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); + } else { + newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); + } } else { newVol = volumeMgr.allocateDuplicateVolume(root, null); } diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index 6a9711401c9..5eedfa5d815 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -24,10 +24,8 @@ import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; import java.lang.reflect.Field; import java.util.List; @@ -64,6 +62,7 @@ import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountService; @@ -200,6 +199,7 @@ public class UserVmManagerTest { doReturn(false).when(_rootVols).isEmpty(); when(_rootVols.get(eq(0))).thenReturn(_volumeMock); doReturn(3L).when(_volumeMock).getTemplateId(); + doReturn(ImageFormat.VHD).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); @@ -220,6 +220,40 @@ public class UserVmManagerTest { } + // Test restoreVM on providing new ISO Id, when VM(deployed using ISO) is in running state + @Test + public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, + ConcurrentOperationException, ResourceAllocationException { + doReturn(VirtualMachine.State.Running).when(_vmMock).getState(); + when(_vmDao.findById(anyLong())).thenReturn(_vmMock); + when(_volsDao.findByInstanceAndType(314L, Volume.Type.ROOT)).thenReturn(_rootVols); + doReturn(false).when(_rootVols).isEmpty(); + when(_rootVols.get(eq(0))).thenReturn(_volumeMock); + doReturn(null).when(_volumeMock).getTemplateId(); + doReturn(3L).when(_vmMock).getIsoId(); + doReturn(ImageFormat.ISO).when(_templateMock).getFormat(); + when(_templateDao.findById(anyLong())).thenReturn(_templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); + when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); + doNothing().when(_vmMock).setIsoId(14L); + when(_templateMock.getGuestOSId()).thenReturn(5L); + doNothing().when(_vmMock).setGuestOSId(anyLong()); + doNothing().when(_vmMock).setTemplateId(3L); + when(_vmDao.update(314L, _vmMock)).thenReturn(true); + when(_itMgr.start(_vmMock, null, _userMock, _account)).thenReturn(_vmMock); + when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); + doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); + when(_volumeMock.getId()).thenReturn(3L); + doNothing().when(_volsDao).detachVolume(anyLong()); + + when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); + + _userVmMgr.restoreVMInternal(_account, _vmMock, 14L); + + verify(_vmMock, times(1)).setIsoId(14L); + + } // Test scaleVm on incompatible HV. @Test(expected=InvalidParameterValueException.class) public void testScaleVMF1() throws Exception { From 8b9d6d81a229441cc5a9e3c0bf61e81de9ea6c5d Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 24 May 2013 17:28:11 +0530 Subject: [PATCH 119/201] Implicit dedication mode --- ui/scripts/configuration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 9932cdc3aa6..211d7b786b7 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -171,7 +171,7 @@ var items=[]; items.push({id:'',description:''}); items.push({id:'Strict', description:'Strict'}); - items.push({id:'Preffered', description:'Preffered'}); + items.push({id:'Preferred', description:'Preferred'}); args.response.success({data:items}); } }, From b000781bfc25b8df1b7b1c8c76bf57484a4c4f03 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Fri, 24 May 2013 18:51:24 +0530 Subject: [PATCH 120/201] fixing disassociateIpAddress API to call 'releasePortableIpAddress' network service method for portable ip address. Also fix ensures events coresponding to the portabl ip are generated correctly. --- api/src/com/cloud/event/EventTypes.java | 2 +- .../api/command/user/address/AssociateIPAddrCmd.java | 6 +++++- .../api/command/user/address/DisassociateIPAddrCmd.java | 8 ++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index fcac8e8e65d..da96294c14c 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -103,7 +103,7 @@ public class EventTypes { public static final String EVENT_NET_IP_ASSIGN = "NET.IPASSIGN"; public static final String EVENT_NET_IP_RELEASE = "NET.IPRELEASE"; public static final String EVENT_PORTABLE_IP_ASSIGN = "PORTABLE.IPASSIGN"; - public static final String EVENT_PORTABLE_IP_RELEASE = "PORTABLEIPRELEASE"; + public static final String EVENT_PORTABLE_IP_RELEASE = "PORTABLE.IPRELEASE"; public static final String EVENT_NET_RULE_ADD = "NET.RULEADD"; public static final String EVENT_NET_RULE_DELETE = "NET.RULEDELETE"; public static final String EVENT_NET_RULE_MODIFY = "NET.RULEMODIFY"; diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index f37e82060fb..b99ca6347e0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -191,7 +191,11 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public String getEventType() { - return EventTypes.EVENT_NET_IP_ASSIGN; + if (isPortable()) { + return EventTypes.EVENT_PORTABLE_IP_ASSIGN; + } else { + return EventTypes.EVENT_NET_IP_ASSIGN; + } } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java index 41691ea86d0..3d431f4ac03 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java @@ -78,7 +78,7 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { if (!isPortable(id)) { result = _networkService.releaseIpAddress(getIpAddressId()); } else { - result = _networkService.releaseIpAddress(getIpAddressId()); + result = _networkService.releasePortableIpAddress(getIpAddressId()); } if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); @@ -90,7 +90,11 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public String getEventType() { - return EventTypes.EVENT_NET_IP_RELEASE; + if (!isPortable(id)) { + return EventTypes.EVENT_NET_IP_RELEASE; + } else { + return EventTypes.EVENT_PORTABLE_IP_RELEASE; + } } @Override From d8f5f2ea10eca540c10e93469fd5307fe25f0959 Mon Sep 17 00:00:00 2001 From: Jayapal Date: Fri, 24 May 2013 17:43:58 +0530 Subject: [PATCH 121/201] CLOUDSTACK-2671 Updated vpc private gateway scipt args --- .../com/cloud/hypervisor/vmware/resource/VmwareResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 be4775452f3..630d1b42e50 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 @@ -1527,7 +1527,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa snatArgs += "eth" + ethDeviceNum; Pair result_gateway = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, - "/opt/cloud/bin/vpc_privateGateway.sh " + args); + "/opt/cloud/bin/vpc_privateGateway.sh " + snatArgs); if (!result_gateway.first()) { throw new InternalErrorException("Unable to configure source NAT for public IP address."); From ed2ce2737133de6277bba0be9b7e10d3faaf887d Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 24 May 2013 19:21:40 +0530 Subject: [PATCH 122/201] CLOUDSTACK-2652: requests module differs on Python 2.6 On 2.6 response.json returns the JSOn in the response while on 2.7 response.json() is a method. Since Marvin installs on both platforms fixing the error appropriately Signed-off-by: Prasanna Santhanam --- tools/marvin/marvin/cloudstackConnection.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index e3977dcf7d4..b092ef0c32f 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -219,7 +219,10 @@ class cloudConnection(object): cmdname, self.auth, payload=payload, method=method) self.logging.debug("Request: %s Response: %s" % (response.url, response.text)) - response = jsonHelper.getResultObj(response.json(), response_type) + try: + response = jsonHelper.getResultObj(response.json(), response_type) + except TypeError: + response = jsonHelper.getResultObj(response.json, response_type) if isAsync == "false": return response From bef3a2edb7f23035a7d397d2d68caf6cecc0f497 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 24 May 2013 12:09:07 +0200 Subject: [PATCH 123/201] CLOUDSTACK-1191: rbd: Use cloning for deploying templates instead of a copy RBD format 2 supports cloning (aka layering) where one base image can serve as a parent image for multiple child images. This enables fast deployment of a large amount of virtual machines, but it also saves spaces on the Ceph cluster and improves performance due to better caching. Qemu-img doesn't support RBD format 2 (yet), so to enable these functions the RADOS/RBD Java bindings are required. This patch also enables deployment of System VMs on RBD storage pools. Since we no longer require a patchdisk for passing the boot arguments we are able to deploy these VMs on RBD. --- .../AbstractStoragePoolAllocator.java | 6 - plugins/hypervisors/kvm/pom.xml | 9 + .../resource/LibvirtComputingResource.java | 7 + .../kvm/storage/LibvirtStorageAdaptor.java | 248 ++++++++++++++++-- pom.xml | 1 + 5 files changed, 246 insertions(+), 25 deletions(-) diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index 3a66b859b39..53267013412 100755 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -167,12 +167,6 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement return false; } - DiskOfferingVO diskOffering = _diskOfferingDao.findById(dskCh.getDiskOfferingId()); - if (diskOffering.getSystemUse() && pool.getPoolType() == StoragePoolType.RBD) { - s_logger.debug("Skipping RBD pool " + pool.getName() + " as a suitable pool. RBD is not supported for System VM's"); - return false; - } - Long clusterId = pool.getClusterId(); ClusterVO cluster = _clusterDao.findById(clusterId); diff --git a/plugins/hypervisors/kvm/pom.xml b/plugins/hypervisors/kvm/pom.xml index 613c817668e..1babe7cbf56 100644 --- a/plugins/hypervisors/kvm/pom.xml +++ b/plugins/hypervisors/kvm/pom.xml @@ -24,6 +24,10 @@ libvirt-org http://libvirt.org/maven2 + + ceph-com + http://ceph.com/maven + @@ -36,6 +40,11 @@ libvirt ${cs.libvirt-java.version} + + com.ceph + rados + ${cs.rados-java.version} + install diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 1e20d75a6a0..c34d1eb1821 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1253,6 +1253,13 @@ ServerResource { } private CopyVolumeAnswer execute(CopyVolumeCommand cmd) { + /** + This method is only used for copying files from Primary Storage TO Secondary Storage + + It COULD also do it the other way around, but the code in the ManagementServerImpl shows + that it always sets copyToSecondary to true + + */ boolean copyToSecondary = cmd.toSecondaryStorage(); String volumePath = cmd.getVolumePath(); StorageFilerTO pool = cmd.getPool(); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index e7e4bbf2c30..fa2f6707923 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -17,6 +17,9 @@ package com.cloud.hypervisor.kvm.storage; import java.io.File; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -37,6 +40,12 @@ import org.libvirt.StoragePool; import org.libvirt.StoragePoolInfo; import org.libvirt.StorageVol; import org.libvirt.StoragePoolInfo.StoragePoolState; +import com.ceph.rados.Rados; +import com.ceph.rados.RadosException; +import com.ceph.rados.IoCTX; +import com.ceph.rbd.Rbd; +import com.ceph.rbd.RbdImage; +import com.ceph.rbd.RbdException; import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.hypervisor.kvm.resource.LibvirtConnection; @@ -63,6 +72,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { private String _mountPoint = "/mnt"; private String _manageSnapshotPath; + private String rbdTemplateSnapName = "cloudstack-base-snap"; + public LibvirtStorageAdaptor(StorageLayer storage) { _storageLayer = storage; _manageSnapshotPath = Script.findScript("scripts/storage/qcow2/", @@ -638,6 +649,15 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } } + /** + * This function copies a physical disk from Secondary Storage to Primary Storage + * or from Primary to Primary Storage + * + * The first time a template is deployed in Primary Storage it will be copied from + * Secondary to Primary. + * + * If it has been created on Primary Storage, it will be copied on the Primary Storage + */ @Override public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) { @@ -690,21 +710,118 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { if (srcPool.getType() != StoragePoolType.RBD) { srcFile = new QemuImgFile(template.getPath(), template.getFormat()); + qemu.convert(srcFile, destFile); } else { - template.setFormat(PhysicalDiskFormat.RAW); - srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), - srcPool.getSourcePort(), - srcPool.getAuthUserName(), - srcPool.getAuthSecret(), - template.getPath())); - srcFile.setFormat(template.getFormat()); + + /** + * We have to find out if the source file is in the same RBD pool and has + * RBD format 2 before we can do a layering/clone operation on the RBD image + * + * This will be the case when the template is already on Primary Storage and + * we want to copy it + */ + + /* Feature 1<<0 means layering in RBD format 2 */ + int rbdFeatures = (1<<0); + /* Order 0 means 4MB blocks (the default) */ + int rbdOrder = 0; + + try { + if ((srcPool.getSourceHost().equals(destPool.getSourceHost())) && (srcPool.getSourceDir().equals(destPool.getSourceDir()))) { + /* We are on the same Ceph cluster, but we require RBD format 2 on the source image */ + s_logger.debug("Trying to perform a RBD clone (layering) since we are operating in the same storage pool"); + + Rados r = new Rados(srcPool.getAuthUserName()); + r.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort()); + r.confSet("key", srcPool.getAuthSecret()); + r.connect(); + s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host")); + + IoCTX io = r.ioCtxCreate(srcPool.getSourceDir()); + Rbd rbd = new Rbd(io); + RbdImage srcImage = rbd.open(template.getName()); + + if (srcImage.isOldFormat()) { + /* The source image is RBD format 1, we have to do a regular copy */ + s_logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + + " is RBD format 1. We have to perform a regular copy (" + template.getVirtualSize() + " bytes)"); + + rbd.create(disk.getName(), template.getVirtualSize(), rbdFeatures, rbdOrder); + RbdImage destImage = rbd.open(disk.getName()); + + s_logger.debug("Starting to copy " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir()); + rbd.copy(srcImage, destImage); + + s_logger.debug("Finished copying " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir()); + rbd.close(destImage); + } else { + s_logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + + " is RBD format 2. We will perform a RBD clone using snapshot " + + this.rbdTemplateSnapName); + /* The source image is format 2, we can do a RBD snapshot+clone (layering) */ + rbd.clone(template.getName(), this.rbdTemplateSnapName, io, disk.getName(), rbdFeatures, rbdOrder); + s_logger.debug("Succesfully cloned " + template.getName() + "@" + this.rbdTemplateSnapName + " to " + disk.getName()); + } + + rbd.close(srcImage); + r.ioCtxDestroy(io); + } else { + /* The source pool or host is not the same Ceph cluster, we do a simple copy with Qemu-Img */ + s_logger.debug("Both the source and destination are RBD, but not the same Ceph cluster. Performing a copy"); + + Rados rSrc = new Rados(srcPool.getAuthUserName()); + rSrc.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort()); + rSrc.confSet("key", srcPool.getAuthSecret()); + rSrc.connect(); + s_logger.debug("Succesfully connected to source Ceph cluster at " + rSrc.confGet("mon_host")); + + Rados rDest = new Rados(destPool.getAuthUserName()); + rDest.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort()); + rDest.confSet("key", destPool.getAuthSecret()); + rDest.connect(); + s_logger.debug("Succesfully connected to source Ceph cluster at " + rDest.confGet("mon_host")); + + IoCTX sIO = rSrc.ioCtxCreate(srcPool.getSourceDir()); + Rbd sRbd = new Rbd(sIO); + + IoCTX dIO = rDest.ioCtxCreate(destPool.getSourceDir()); + Rbd dRbd = new Rbd(dIO); + + s_logger.debug("Creating " + disk.getName() + " on the destination cluster " + rDest.confGet("mon_host") + + " in pool " + destPool.getSourceDir()); + dRbd.create(disk.getName(), template.getVirtualSize(), rbdFeatures, rbdOrder); + + RbdImage srcImage = sRbd.open(template.getName()); + RbdImage destImage = dRbd.open(disk.getName()); + + s_logger.debug("Copying " + template.getName() + " from Ceph cluster " + rSrc.confGet("mon_host") + " to " + disk.getName() + + " on cluster " + rDest.confGet("mon_host")); + sRbd.copy(srcImage, destImage); + + sRbd.close(srcImage); + dRbd.close(destImage); + + rSrc.ioCtxDestroy(sIO); + rDest.ioCtxDestroy(dIO); + } + } catch (RadosException e) { + s_logger.error("Failed to perform a RADOS action on the Ceph cluster, the error was: " + e.getMessage()); + disk = null; + } catch (RbdException e) { + s_logger.error("Failed to perform a RBD action on the Ceph cluster, the error was: " + e.getMessage()); + disk = null; + } } - qemu.convert(srcFile, destFile); } } catch (QemuImgException e) { s_logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage()); } + + if (disk == null) { + throw new CloudRuntimeException("Failed to create " + disk.getPath() + " from template " + template.getName()); + } + return disk; } @@ -733,17 +850,26 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } } + /** + * This copies a volume from Primary Storage to Secondary Storage + * + * In theory it could also do it the other way around, but the current implementation + * in ManagementServerImpl shows that the destPool is always a Secondary Storage Pool + */ @Override public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPool) { - /* + /** With RBD you can't run qemu-img convert with an existing RBD image as destination qemu-img will exit with the error that the destination already exists. So for RBD we don't create the image, but let qemu-img do that for us. We then create a KVMPhysicalDisk object that we can return - */ + + It is however very unlikely that the destPool will be RBD, since it isn't supported + for Secondary Storage + */ KVMPhysicalDisk newDisk; if (destPool.getType() != StoragePoolType.RBD) { @@ -791,15 +917,97 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { + srcFile.getFileName() + " the error was: " + e.getMessage()); } } + + try { + qemu.convert(srcFile, destFile); + } catch (QemuImgException e) { + s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + + destFile.getFileName() + " the error was: " + e.getMessage()); + } + } else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD)) { - srcFile = new QemuImgFile(sourcePath, sourceFormat); - destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), - destPool.getSourcePort(), - destPool.getAuthUserName(), - destPool.getAuthSecret(), - destPath)); - destFile.setFormat(destFormat); + /** + * Qemu doesn't support writing to RBD format 2 directly, so we have to write to a temporary RAW file first + * which we then convert to RBD format 2. + * + * A HUGE performance gain can be achieved here if QCOW2 -> RBD format 2 can be done in one step + */ + s_logger.debug("The source image is not RBD, but the destination is. We will convert into RBD format 2"); + String tmpFile = "/tmp/" + name; + int rbdFeatures = (1<<0); + int rbdOrder = 0; + + try { + srcFile = new QemuImgFile(sourcePath, sourceFormat); + destFile = new QemuImgFile(tmpFile); + s_logger.debug("Converting " + srcFile.getFileName() + " to " + tmpFile + " as a temporary file for RBD conversion"); + qemu.convert(srcFile, destFile); + + // We now convert the temporary file to a RBD image with format 2 + Rados r = new Rados(destPool.getAuthUserName()); + r.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort()); + r.confSet("key", destPool.getAuthSecret()); + r.connect(); + s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host")); + + IoCTX io = r.ioCtxCreate(destPool.getSourceDir()); + Rbd rbd = new Rbd(io); + + s_logger.debug("Creating RBD image " + name + " in Ceph pool " + destPool.getSourceDir() + " with RBD format 2"); + rbd.create(name, disk.getVirtualSize(), rbdFeatures, rbdOrder); + + RbdImage image = rbd.open(name); + + // We now read the temporary file and write it to the RBD image + File fh = new File(tmpFile); + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fh)); + + int chunkSize = 4194304; + long offset = 0; + s_logger.debug("Reading temporary file " + tmpFile + " (" + fh.length() + " bytes) into RBD image " + name + " in chunks of " + chunkSize + " bytes"); + while(true) { + byte[] buf = new byte[chunkSize]; + + int bytes = bis.read(buf); + if (bytes <= 0) { + break; + } + image.write(buf, offset, bytes); + offset += bytes; + } + s_logger.debug("Completed writing " + tmpFile + " to RBD image " + name + ". Bytes written: " + offset); + bis.close(); + s_logger.debug("Removing temporary file " + tmpFile); + fh.delete(); + + /* Snapshot the image and protect that snapshot so we can clone (layer) from it */ + s_logger.debug("Creating RBD snapshot " + this.rbdTemplateSnapName + " on image " + name); + image.snapCreate(this.rbdTemplateSnapName); + s_logger.debug("Protecting RBD snapshot " + this.rbdTemplateSnapName + " on image " + name); + image.snapProtect(this.rbdTemplateSnapName); + + rbd.close(image); + r.ioCtxDestroy(io); + } catch (QemuImgException e) { + s_logger.error("Failed to do a temp convert from " + srcFile.getFileName() + " to " + + destFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; + } catch (RadosException e) { + s_logger.error("A Ceph RADOS operation failed (" + e.getReturnValue() + "). The error was: " + e.getMessage()); + newDisk = null; + } catch (RbdException e) { + s_logger.error("A Ceph RBD operation failed (" + e.getReturnValue() + "). The error was: " + e.getMessage()); + newDisk = null; + } catch (IOException e) { + s_logger.error("Failed reading the temporary file during the conversion to RBD: " + e.getMessage()); + newDisk = null; + } + } else { + /** + We let Qemu-Img do the work here. Although we could work with librbd and have that do the cloning + it doesn't benefit us. It's better to keep the current code in place which works + */ srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), srcPool.getSourcePort(), srcPool.getAuthUserName(), @@ -812,17 +1020,19 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { destPool.getAuthSecret(), destPath)); destFile.setFormat(destFormat); - } - if (srcFile != null && destFile != null) { try { qemu.convert(srcFile, destFile); } catch (QemuImgException e) { s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; } } + if (newDisk == null) { + throw new CloudRuntimeException("Failed to copy " + disk.getPath() + " to " + name); + } return newDisk; } diff --git a/pom.xml b/pom.xml index d7e80d64548..67d9576715c 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,7 @@ 0.10 build/replace.properties 0.4.9 + 0.1.1 target 1.0.10 From 09d2fe6a7ddc208f77edf931ed3d57b0afcc2055 Mon Sep 17 00:00:00 2001 From: Chip Childers Date: Fri, 24 May 2013 17:06:02 +0100 Subject: [PATCH 124/201] CLOUDSTACK-528: Adding a corrective update to remove the extra space characters that exist after running older versions of schema-302to40.sql Signed-off-by: Chip Childers --- setup/db/db/schema-40to410.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index acc29a2eb7f..f0e8cf31846 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -1653,3 +1653,7 @@ CREATE TABLE `cloud`.`netscaler_pod_ref` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'eip.use.multiple.netscalers' , 'false', 'Should be set to true, if there will be multiple NetScaler devices providing EIP service in a zone'); + +UPDATE `cloud`.`configuration` set category='Advanced' where category='Advanced '; +UPDATE `cloud`.`configuration` set category='Hidden' where category='Hidden '; + From 90a40b0806bf586bca6653023d32bff270944251 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 24 May 2013 21:41:46 +0530 Subject: [PATCH 125/201] Move changeOffering test to service offerings This will reduce the time (>30m) on the vm lifecycle. Signed-off-by: Prasanna Santhanam --- .../smoke/test_service_offerings.py | 366 +++++++++++++----- test/integration/smoke/test_vm_life_cycle.py | 239 ------------ 2 files changed, 276 insertions(+), 329 deletions(-) diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 7f4d130ee80..3d3b94684e8 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -27,24 +27,80 @@ from nose.plugins.attrib import attr _multiprocess_shared_ = True + class Services: """Test Service offerings Services """ def __init__(self): self.services = { - "off": - { - "name": "Service Offering", - "displaytext": "Service Offering", - "cpunumber": 1, - "cpuspeed": 100, # MHz - "memory": 128, # in MBs - }, - } + "off": + { + "name": "Service Offering", + "displaytext": "Service Offering", + "cpunumber": 1, + "cpuspeed": 100, # MHz + "memory": 128, # in MBs + }, + "small": + # Create a small virtual machine instance with disk offering + { + "displayname": "testserver", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "medium": # Create a medium virtual machine instance + { + "displayname": "testserver", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offerings": + { + "tiny": + { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "small": + { + # Small service offering ID to for change VM + # service offering from medium to small + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "medium": + { + # Medium service offering ID to for + # change VM service offering from small to medium + "name": "Medium Instance", + "displaytext": "Medium Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + } + }, + "ostype": 'CentOS 5.3 (64-bit)', + } + class TestCreateServiceOffering(cloudstackTestCase): - def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() @@ -60,8 +116,8 @@ class TestCreateServiceOffering(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_01_create_service_offering(self): """Test to create service offering""" @@ -70,67 +126,65 @@ class TestCreateServiceOffering(cloudstackTestCase): # 2. The Cloud Database contains the valid information service_offering = ServiceOffering.create( - self.apiclient, - self.services["off"] - ) + self.apiclient, + self.services["off"] + ) self.cleanup.append(service_offering) self.debug("Created service offering with ID: %s" % service_offering.id) list_service_response = list_service_offering( - self.apiclient, - id=service_offering.id - ) + self.apiclient, + id=service_offering.id + ) self.assertEqual( - isinstance(list_service_response, list), - True, - "Check list response returns a valid list" - ) - + isinstance(list_service_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( - len(list_service_response), - 0, - "Check Service offering is created" - ) + len(list_service_response), + 0, + "Check Service offering is created" + ) service_response = list_service_response[0] self.assertEqual( - list_service_response[0].cpunumber, - self.services["off"]["cpunumber"], - "Check server id in createServiceOffering" - ) + list_service_response[0].cpunumber, + self.services["off"]["cpunumber"], + "Check server id in createServiceOffering" + ) self.assertEqual( - list_service_response[0].cpuspeed, - self.services["off"]["cpuspeed"], - "Check cpuspeed in createServiceOffering" - ) + list_service_response[0].cpuspeed, + self.services["off"]["cpuspeed"], + "Check cpuspeed in createServiceOffering" + ) self.assertEqual( - list_service_response[0].displaytext, - self.services["off"]["displaytext"], - "Check server displaytext in createServiceOfferings" - ) + list_service_response[0].displaytext, + self.services["off"]["displaytext"], + "Check server displaytext in createServiceOfferings" + ) self.assertEqual( - list_service_response[0].memory, - self.services["off"]["memory"], - "Check memory in createServiceOffering" - ) + list_service_response[0].memory, + self.services["off"]["memory"], + "Check memory in createServiceOffering" + ) self.assertEqual( - list_service_response[0].name, - self.services["off"]["name"], - "Check name in createServiceOffering" - ) + list_service_response[0].name, + self.services["off"]["name"], + "Check name in createServiceOffering" + ) return class TestServiceOfferings(cloudstackTestCase): - def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] def tearDown(self): - try: #Clean up, terminate the created templates cleanup_resources(self.apiclient, self.cleanup) @@ -142,17 +196,61 @@ class TestServiceOfferings(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.services = Services().services cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() + cls.services = Services().services + domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype + cls.service_offering_1 = ServiceOffering.create( - cls.api_client, - cls.services["off"] - ) + cls.api_client, + cls.services["off"] + ) cls.service_offering_2 = ServiceOffering.create( - cls.api_client, - cls.services["off"] - ) - cls._cleanup = [cls.service_offering_1] + cls.api_client, + cls.services["off"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = template.id + + cls.services["medium"]["zoneid"] = cls.zone.id + cls.services["medium"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=domain.id + ) + + cls.small_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["small"] + ) + + cls.medium_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["medium"] + ) + cls.medium_virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["medium"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.medium_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup = [ + cls.small_offering, + cls.medium_offering, + cls.account + ] return @classmethod @@ -166,7 +264,7 @@ class TestServiceOfferings(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_02_edit_service_offering(self): """Test to update existing service offering""" @@ -178,8 +276,8 @@ class TestServiceOfferings(cloudstackTestCase): random_displaytext = random_gen() random_name = random_gen() - self.debug("Updating service offering with ID: %s" % - self.service_offering_1.id) + self.debug("Updating service offering with ID: %s" % + self.service_offering_1.id) cmd = updateServiceOffering.updateServiceOfferingCmd() #Add parameters for API call @@ -189,35 +287,35 @@ class TestServiceOfferings(cloudstackTestCase): self.apiclient.updateServiceOffering(cmd) list_service_response = list_service_offering( - self.apiclient, - id=self.service_offering_1.id - ) + self.apiclient, + id=self.service_offering_1.id + ) self.assertEqual( - isinstance(list_service_response, list), - True, - "Check list response returns a valid list" - ) - + isinstance(list_service_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( - len(list_service_response), - 0, - "Check Service offering is updated" - ) + len(list_service_response), + 0, + "Check Service offering is updated" + ) self.assertEqual( - list_service_response[0].displaytext, - random_displaytext, - "Check server displaytext in updateServiceOffering" - ) + list_service_response[0].displaytext, + random_displaytext, + "Check server displaytext in updateServiceOffering" + ) self.assertEqual( - list_service_response[0].name, - random_name, - "Check server name in updateServiceOffering" - ) + list_service_response[0].name, + random_name, + "Check server name in updateServiceOffering" + ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_03_delete_service_offering(self): """Test to delete service offering""" @@ -225,20 +323,108 @@ class TestServiceOfferings(cloudstackTestCase): # 1. deleteServiceOffering should return # a valid information for newly created offering - self.debug("Deleting service offering with ID: %s" % - self.service_offering_2.id) + self.debug("Deleting service offering with ID: %s" % + self.service_offering_2.id) self.service_offering_2.delete(self.apiclient) list_service_response = list_service_offering( - self.apiclient, - id=self.service_offering_2.id - ) + self.apiclient, + id=self.service_offering_2.id + ) self.assertEqual( - list_service_response, - None, - "Check if service offering exists in listDiskOfferings" - ) + list_service_response, + None, + "Check if service offering exists in listDiskOfferings" + ) return + + @attr(tags=["advanced", "advancedns", "smoke"]) + def test_04_change_offering_small(self): + """Test to change service to a small capacity + """ + # Validate the following + # 1. Log in to the Vm .We should see that the CPU and memory Info of + # this Vm matches the one specified for "Small" service offering. + # 2. Using listVM command verify that this Vm + # has Small service offering Id. + + self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id) + self.medium_virtual_machine.stop(self.apiclient) + # Ensure that VM is in stopped state + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.medium_virtual_machine.id + ) + if isinstance(list_vm_response, list): + vm = list_vm_response[0] + if vm.state == 'Stopped': + self.debug("VM state: %s" % vm.state) + else: + raise Exception( + "Failed to stop VM (ID: %s) in change service offering" % vm.id) + + self.debug("Change Service offering VM - ID: %s" % + self.medium_virtual_machine.id) + + cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() + cmd.id = self.medium_virtual_machine.id + cmd.serviceofferingid = self.small_offering.id + self.apiclient.changeServiceForVirtualMachine(cmd) + + self.debug("Starting VM - ID: %s" % self.medium_virtual_machine.id) + self.medium_virtual_machine.start(self.apiclient) + # Ensure that VM is in running state + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.medium_virtual_machine.id + ) + + if isinstance(list_vm_response, list): + vm = list_vm_response[0] + if vm.state == 'Running': + self.debug("VM state: %s" % vm.state) + else: + raise Exception( + "Failed to start VM (ID: %s) after changing service offering" % vm.id) + + try: + ssh = self.medium_virtual_machine.get_ssh_client() + except Exception as e: + self.fail( + "SSH Access failed for %s: %s" %\ + (self.medium_virtual_machine.ipaddress, e) + ) + + cpuinfo = ssh.execute("cat /proc/cpuinfo") + cpu_cnt = len([i for i in cpuinfo if "processor" in i]) + #'cpu MHz\t\t: 2660.499' + cpu_speed = [i for i in cpuinfo if "cpu MHz" in i][0].split()[3] + meminfo = ssh.execute("cat /proc/meminfo") + #MemTotal: 1017464 kB + total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1] + + self.debug( + "CPU count: %s, CPU Speed: %s, Mem Info: %s" % ( + cpu_cnt, + cpu_speed, + total_mem + )) + self.assertAlmostEqual( + int(cpu_cnt), + self.small_offering.cpunumber, + "Check CPU Count for small offering" + ) + self.assertAlmostEqual( + list_vm_response[0].cpuspeed, + self.small_offering.cpuspeed, + "Check CPU Speed for small offering" + ) + self.assertAlmostEqual( + int(total_mem) / 1024, # In MBs + self.small_offering.memory, + "Check Memory(kb) for small offering" + ) + return diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index d52ed9b8df6..8c78149addf 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -489,245 +489,6 @@ class TestVMLifeCycle(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_04_change_offering_small(self): - """Change Offering to a small capacity - """ - - # Validate the following - # 1. Log in to the Vm .We should see that the CPU and memory Info of - # this Vm matches the one specified for "Small" service offering. - # 2. Using listVM command verify that this Vm - # has Small service offering Id. - - self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id) - - self.medium_virtual_machine.stop(self.apiclient) - - # Poll listVM to ensure VM is stopped properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.medium_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % vm.id) - - timeout = timeout - 1 - - self.debug("Change Service offering VM - ID: %s" % - self.medium_virtual_machine.id) - - cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() - cmd.id = self.medium_virtual_machine.id - cmd.serviceofferingid = self.small_offering.id - self.apiclient.changeServiceForVirtualMachine(cmd) - - self.debug("Starting VM - ID: %s" % self.medium_virtual_machine.id) - self.medium_virtual_machine.start(self.apiclient) - - # Poll listVM to ensure VM is started properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in running state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.medium_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Running': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to start VM (ID: %s) after changing service offering" % vm.id) - - timeout = timeout - 1 - - try: - ssh = self.medium_virtual_machine.get_ssh_client() - except Exception as e: - self.fail( - "SSH Access failed for %s: %s" % \ - (self.medium_virtual_machine.ipaddress, e) - ) - - cpuinfo = ssh.execute("cat /proc/cpuinfo") - - cpu_cnt = len([i for i in cpuinfo if "processor" in i]) - #'cpu MHz\t\t: 2660.499' - cpu_speed = [i for i in cpuinfo if "cpu MHz" in i ][0].split()[3] - - meminfo = ssh.execute("cat /proc/meminfo") - #MemTotal: 1017464 kB - total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1] - - self.debug( - "CPU count: %s, CPU Speed: %s, Mem Info: %s" % ( - cpu_cnt, - cpu_speed, - total_mem - )) - self.assertAlmostEqual( - int(cpu_cnt), - self.small_offering.cpunumber, - "Check CPU Count for small offering" - ) - - self.assertAlmostEqual( - list_vm_response[0].cpuspeed, - self.small_offering.cpuspeed, - "Check CPU Speed for small offering" - ) - self.assertAlmostEqual( - int(total_mem) / 1024, # In MBs - self.small_offering.memory, - "Check Memory(kb) for small offering" - ) - return - - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_05_change_offering_medium(self): - """Change Offering to a medium capacity - """ - # Validate the following - # 1. Log in to the Vm .We should see that the CPU and memory Info of - # this Vm matches the one specified for "Medium" service offering. - # 2. Using listVM command verify that this Vm - # has Medium service offering Id. - - self.debug("Stopping VM - ID: %s" % self.small_virtual_machine.id) - self.small_virtual_machine.stop(self.apiclient) - - # Poll listVM to ensure VM is stopped properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % vm.id) - - timeout = timeout - 1 - - self.debug("Change service offering VM - ID: %s" % - self.small_virtual_machine.id) - - cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() - cmd.id = self.small_virtual_machine.id - cmd.serviceofferingid = self.medium_offering.id - self.apiclient.changeServiceForVirtualMachine(cmd) - - self.debug("Starting VM - ID: %s" % self.small_virtual_machine.id) - self.small_virtual_machine.start(self.apiclient) - - # Poll listVM to ensure VM is started properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in running state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Running': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to start VM (ID: %s) after changing service offering" % vm.id) - - timeout = timeout - 1 - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - try: - ssh_client = self.small_virtual_machine.get_ssh_client() - except Exception as e: - self.fail( - "SSH Access failed for %s: %s" % \ - (self.small_virtual_machine.ipaddress, e) - ) - - cpuinfo = ssh_client.execute("cat /proc/cpuinfo") - - cpu_cnt = len([i for i in cpuinfo if "processor" in i]) - #'cpu MHz\t\t: 2660.499' - cpu_speed = [i for i in cpuinfo if "cpu MHz" in i][0].split()[3] - - meminfo = ssh_client.execute("cat /proc/meminfo") - #MemTotal: 1017464 kB - total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1] - - self.debug( - "CPU count: %s, CPU Speed: %s, Mem Info: %s" % ( - cpu_cnt, - cpu_speed, - total_mem - )) - self.assertAlmostEqual( - int(cpu_cnt), - self.medium_offering.cpunumber, - "Check CPU Count for medium offering" - ) - - self.assertAlmostEqual( - list_vm_response[0].cpuspeed, - self.medium_offering.cpuspeed, - "Check CPU Speed for medium offering" - ) - - self.assertAlmostEqual( - int(total_mem) / 1024, # In MBs - self.medium_offering.memory, - "Check Memory(kb) for medium offering" - ) - return @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) def test_06_destroy_vm(self): From 6975f6bac6b33d208bd68750457369ef0178c50f Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 24 May 2013 10:08:55 -0700 Subject: [PATCH 126/201] CLOUDSTACK-2377: UI - network menu - add guest network dialog only allows to add Isolated network, but not shared network. Change label to make it clear. --- ui/scripts/network.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 3eef1367e97..0ffaa1dce2f 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -321,7 +321,7 @@ listView: { actions: { add: { //add Isolated guest network (can't add Shared guest network here) - label: 'label.add.guest.network', + label: 'Add Isolated Guest Network', preFilter: function(args) { //Isolated networks is only supported in Advanced (SG-disabled) zone if(args.context.zoneType != 'Basic') @@ -331,8 +331,8 @@ }, createForm: { - title: 'label.add.guest.network', - desc: 'message.add.guest.network', + title: 'Add Isolated Guest Network', + desc: 'Add Isolated Guest Network with SourceNat', fields: { name: { label: 'label.name', validation: { required: true }, docID: 'helpGuestNetworkName' }, displayText: { label: 'label.display.text', validation: { required: true }, docID: 'helpGuestNetworkDisplayText'}, @@ -497,7 +497,7 @@ }); }, messages: { - notification: function() { return 'label.add.guest.network'; } + notification: function() { return 'Add Isolated Guest Network'; } } } }, From 3d16e82547c311c1f0cd22065d587556d70d511a Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 24 May 2013 10:33:28 -0700 Subject: [PATCH 127/201] CLOUDSTACK-2678: portable IP ranges - regions detailView - add viewAll path to Portable IP Ranges listView. --- ui/scripts/regions.js | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index 2bbbbeea672..e86fd283aad 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -116,7 +116,10 @@ }, detailView: { name: 'Region details', - viewAll: { path: 'regions.GSLB', label: 'GSLB' }, + viewAll: [ + { path: 'regions.GSLB', label: 'GSLB' }, + { path: 'regions.portableIpRanges', label: 'Portable IP' } + ], actions: { edit: { label: 'label.edit.region', @@ -451,8 +454,40 @@ } } }, - - lbUnderGSLB: { + + portableIpRanges: { + id: 'portableIpRanges', + type: 'select', + title: 'Portable IP Ranges', + listView: { + id: 'portableIpRanges', + label: 'Portable IP Ranges', + fields: { + name: { label: 'label.name' }, + gslbdomainname: { label: 'GSLB Domain Name' }, + gslblbmethod: { label: 'Algorithm' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listPortableIpRanges'), + data: { + regionid: args.context.regions[0].id + }, + success: function(json) { + var items = json.listportableipresponse.portableip; + args.response.success({ + data: items + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + }, + + lbUnderGSLB: { id: 'lbUnderGSLB', type: 'select', title: 'assigned load balancing', From 52a4962f4d3d83fc0eb3c60dbd6b5817a05eae9a Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 24 May 2013 12:06:09 -0700 Subject: [PATCH 128/201] If no tiers are present, show add tier dialog on load --- ui/modules/vpc/vpc.js | 141 +++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index e313b8ab2b5..302ab6cb388 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -15,6 +15,53 @@ // specific language governing permissions and limitations // under the License. (function($, cloudStack) { + var addTierDialog = function(args) { + var $placeholder = args.$placeholder; + var context = args.context; + var addAction = cloudStack.vpc.tiers.actions.add; + + cloudStack.dialog.createForm({ + context: context, + form: addAction.createForm, + after: function(args) { + var $loading = $('
    ').addClass('loading-overlay') + .prependTo($placeholder); + + addAction.action({ + context: context, + data: args.data, + response: { + success: function(args) { + cloudStack.ui.notifications.add( + // Notification + { + desc: addAction.label + }, + + // Success + function(args) { + $loading.remove(); + $placeholder.closest('.vpc-network-chart').trigger('reload'); + }, + + {}, + + // Error + function(args) { + $loading.remove(); + } + ); + }, + error: function(errorMsg) { + cloudStack.dialog.notice({ message: _s(errorMsg) }); + $loading.remove(); + } + } + }); + } + }); + }; + var elems = { tier: function(args) { var tier = args.tier; @@ -74,10 +121,10 @@ }, dashboardItems: args.dashboardItems }).addClass('router'); - + $router.find('.info, .detail-link').remove(); $router.find('.header').prepend($('').addClass('icon').html(' ')); - + return $router; }, @@ -87,66 +134,12 @@ $placeholder.append($('').append('Create network')); $placeholder.click(function() { - var addAction = cloudStack.vpc.tiers.actions.add; - var form = cloudStack.dialog.createForm({ + addTierDialog({ context: context, - form: addAction.createForm, - after: function(args) { - var $loading = $('
    ').addClass('loading-overlay') - .prependTo($placeholder); - - addAction.action({ - context: context, - data: args.data, - response: { - success: function(args) { - var tier = args.data; - - cloudStack.ui.notifications.add( - // Notification - { - desc: addAction.label - }, - - // Success - function(args) { - $loading.remove(); - $placeholder.closest('.vpc-network-chart').trigger('reload'); - - // addNewTier({ - // ipAddresses: ipAddresses, - // $browser: $browser, - // tierDetailView: tierDetailView, - // context: $.extend(true, {}, context, { - // networks: [tier] - // }), - // tier: tier, - // acl: acl, - // $tiers: $tiers, - // actions: actions, - // actionPreFilter: actionPreFilter, - // vmListView: vmListView - // }); - }, - - {}, - - // Error - function(args) { - $loading.remove(); - } - ); - }, - error: function(errorMsg) { - cloudStack.dialog.notice({ message: _s(errorMsg) }); - $loading.remove(); - } - } - }); - } + $placeholder: $placeholder }); }); - + return $placeholder; }, @@ -170,7 +163,7 @@ } else { $total.find('span').html(dashboardItem.total ? dashboardItem.total : 0); } - + $dashboardItem.append($total, $name); $dashboardItem.appendTo($dashboard); @@ -214,7 +207,7 @@ var vpcChart = function(args) { var context = args.context; var vpcItem = context.vpc[0]; - + var chart = function(args) { args = args ? args : {}; @@ -232,6 +225,9 @@ response: { success: function(data) { var tiers = data.tiers; + var $placeholder = elems.tierPlaceholder({ + context: context + }); $(tiers).map(function(index, tier) { var $tier = elems.tier({ @@ -239,34 +235,37 @@ tier: tier, dashboardItems: tier._dashboardItems }); - $tier.appendTo($tiers); }); // Add placeholder tier - $tiers.append(elems.tierPlaceholder({ - context: context - })); - + $tiers.append($placeholder); $loading.remove(); - + + if (!tiers.length) { + addTierDialog({ + context: context, + $placeholder: $placeholder + }); + } + if (args.complete) { args.complete($chart); } - + // Router - $router = elems.router({ + elems.router({ context: context, dashboardItems: data.routerDashboard }).appendTo($chart); } - } + } }); $chart.bind('reload', function() { chart({ complete: function($newChart) { - $chart.replaceWith($newChart); + $chart.replaceWith($newChart); } }); }); From 489396940e2487fa6254c837873dfd71bdd3de67 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 24 May 2013 12:06:58 -0700 Subject: [PATCH 129/201] Update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 016554a5f75..929227d8604 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,4 @@ debian/*.debhelper replace.properties.tmp build-indep-stamp configure-stamp +*_flymake.js \ No newline at end of file From 6f65a5bbe7635e0b0b81143bcb61fd2a428231f8 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 24 May 2013 12:06:58 -0700 Subject: [PATCH 130/201] Update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 016554a5f75..929227d8604 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,4 @@ debian/*.debhelper replace.properties.tmp build-indep-stamp configure-stamp +*_flymake.js \ No newline at end of file From cd7287a4e17c605be71910b260540dfa685f4ef8 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 24 May 2013 13:06:51 -0700 Subject: [PATCH 131/201] Site-to-site VPN UI: Show confirm dialog if no gateways exist --- ui/modules/vpc/vpc.js | 67 ++++++++++++++++++++++++++++++++----------- ui/scripts/vpc.js | 43 ++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 302ab6cb388..6eb721a9a2b 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -168,27 +168,60 @@ $dashboardItem.appendTo($dashboard); $dashboardItem.click(function() { - $('#browser .container').cloudBrowser('addPanel', { - title: tier.name + ' - ' + dashboardItem.name, - maximizeIfSelected: true, - complete: function($panel) { - var section = cloudStack.vpc.sections[id]; - var $section = $('
    '); + var section = cloudStack.vpc.sections[id]; + var $section = $('
    '); + var $loading = $('
    ').addClass('loading-overlay'); + + if ($.isFunction(section)) { + section = cloudStack.vpc.sections[id](); + } - if ($.isFunction(section)) { - section = cloudStack.vpc.sections[id](); + var before = section.before; + var load = function() { + $('#browser .container').cloudBrowser('addPanel', { + title: tier.name + ' - ' + dashboardItem.name, + maximizeIfSelected: true, + complete: function($panel) { + if (section.listView) { + $section.listView($.extend(true, {}, section, { + onActionComplete: function() { + $dashboardItem.closest('.vpc-network-chart').trigger('reload'); + }, + context: context + })); + } + + $section.appendTo($panel); } + }); + }; - if (section.listView) { - $section.listView($.extend(true, {}, section, { - onActionComplete: function() { - $dashboardItem.closest('.vpc-network-chart').trigger('reload'); - }, - context: context - })); + before.check({ + context: context, + response: { + success: function(result) { + // true means content exists + if (result) { + load(); + } else { + cloudStack.dialog.confirm({ + message: before.messages.confirm, + action: function() { + $loading.appendTo($dashboardItem.closest('.vpc-network-chart')); + before.action({ + context: context, + response: { + success: function() { + $loading.remove(); + $dashboardItem.closest('.vpc-network-chart').trigger('reload'); + load(); + } + } + }); + } + }) + } } - - $section.appendTo($panel); } }); }); diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 2183aba55fd..3581b88ea34 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -801,7 +801,48 @@ // 'listView' block // // -- use this as a flag for VPC chart to render as a list view - listView: true + listView: true, + before: { + messages: { + confirm: 'Please confirm that you would like to create a site-to-site VPN gateway for this VPC.', + notification: 'Create site-to-site VPN gateway' + }, + check: function(args) { + var items; + + $.ajax({ + url: createURL('listVpnGateways&listAll=true'), + data: { + vpcid: args.context.vpc[0].id + }, + success: function(json) { + var items = json.listvpngatewaysresponse.vpngateway; + + args.response.success(items && items.length); + } + }); + }, + action: function(args) { + $.ajax({ + url: createURL("createVpnGateway"), + data: { + vpcid: args.context.vpc[0].id + }, + success: function(json) { + var jid = json.createvpngatewayresponse.jobid; + var pollTimer = setInterval(function() { + pollAsyncJobResult({ + _custom: { jobId: jid }, + complete: function() { + clearInterval(pollTimer); + args.response.success(); + } + }); + }, g_queryAsyncJobResultInterval); + } + }); + } + } }); } }, From 72fa89eb7a326582abac2554a25786f339ef58ca Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 24 May 2013 13:07:42 -0700 Subject: [PATCH 132/201] Fix for dashboard items without before: {} block --- ui/modules/vpc/vpc.js | 52 ++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 6eb721a9a2b..1a3b3e82001 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -196,34 +196,36 @@ }); }; - before.check({ - context: context, - response: { - success: function(result) { - // true means content exists - if (result) { - load(); - } else { - cloudStack.dialog.confirm({ - message: before.messages.confirm, - action: function() { - $loading.appendTo($dashboardItem.closest('.vpc-network-chart')); - before.action({ - context: context, - response: { - success: function() { - $loading.remove(); - $dashboardItem.closest('.vpc-network-chart').trigger('reload'); - load(); + if (before) { + before.check({ + context: context, + response: { + success: function(result) { + // true means content exists + if (result) { + load(); + } else { + cloudStack.dialog.confirm({ + message: before.messages.confirm, + action: function() { + $loading.appendTo($dashboardItem.closest('.vpc-network-chart')); + before.action({ + context: context, + response: { + success: function() { + $loading.remove(); + $dashboardItem.closest('.vpc-network-chart').trigger('reload'); + load(); + } } - } - }); - } - }) + }); + } + }) + } } } - } - }); + }); + } }); }); From 2a966f35ff05e458e1d4df230920cdd926309cac Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Fri, 24 May 2013 13:10:31 -0700 Subject: [PATCH 133/201] Another fix for before: {} block --- ui/modules/vpc/vpc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js index 1a3b3e82001..a6037c00fb7 100644 --- a/ui/modules/vpc/vpc.js +++ b/ui/modules/vpc/vpc.js @@ -225,6 +225,8 @@ } } }); + } else { + load(); } }); }); From 2ecf9e3293d9b5f1ccffe0736bc8ef0cbf3b1529 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Fri, 24 May 2013 14:08:28 -0700 Subject: [PATCH 134/201] CLOUDSTACK-2680: Async job expunge thread - expunge only: 1) Unfinished jobs that are yet to be processed. 2) Completed jobs The jobs that are in process, will be skipped by the expunge thread Conflicts: server/src/com/cloud/async/dao/AsyncJobDao.java server/src/com/cloud/async/dao/AsyncJobDaoImpl.java server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java --- .../com/cloud/async/AsyncJobManagerImpl.java | 17 ++-- .../src/com/cloud/async/dao/AsyncJobDao.java | 5 +- .../com/cloud/async/dao/AsyncJobDaoImpl.java | 88 ++++++++++++------- 3 files changed, 70 insertions(+), 40 deletions(-) diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java index 47d793fd0b0..0101a8a0abf 100644 --- a/server/src/com/cloud/async/AsyncJobManagerImpl.java +++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java @@ -621,11 +621,18 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, // limit to 100 jobs per turn, this gives cleanup throughput as 600 jobs per minute // hopefully this will be fast enough to balance potential growth of job table - List l = _jobDao.getExpiredJobs(cutTime, 100); - if(l != null && l.size() > 0) { - for(AsyncJobVO job : l) { - expungeAsyncJob(job); - } + //1) Expire unfinished jobs that weren't processed yet + List l = _jobDao.getExpiredUnfinishedJobs(cutTime, 100); + for(AsyncJobVO job : l) { + s_logger.trace("Expunging unfinished job " + job); + expungeAsyncJob(job); + } + + //2) Expunge finished jobs + List completedJobs = _jobDao.getExpiredCompletedJobs(cutTime, 100); + for(AsyncJobVO job : completedJobs) { + s_logger.trace("Expunging completed job " + job); + expungeAsyncJob(job); } // forcefully cancel blocking queue items if they've been staying there for too long diff --git a/server/src/com/cloud/async/dao/AsyncJobDao.java b/server/src/com/cloud/async/dao/AsyncJobDao.java index 9d207593574..9ab9b224c10 100644 --- a/server/src/com/cloud/async/dao/AsyncJobDao.java +++ b/server/src/com/cloud/async/dao/AsyncJobDao.java @@ -26,6 +26,7 @@ import com.cloud.utils.db.GenericDao; public interface AsyncJobDao extends GenericDao { AsyncJobVO findInstancePendingAsyncJob(String instanceType, long instanceId); List findInstancePendingAsyncJobs(AsyncJob.Type instanceType, Long accountId); - List getExpiredJobs(Date cutTime, int limit); + List getExpiredUnfinishedJobs(Date cutTime, int limit); void resetJobProcess(long msid, int jobResultCode, String jobResultMessage); -} + List getExpiredCompletedJobs(Date cutTime, int limit); +} \ No newline at end of file diff --git a/server/src/com/cloud/async/dao/AsyncJobDaoImpl.java b/server/src/com/cloud/async/dao/AsyncJobDaoImpl.java index 4793a6edc12..b2c0d9cc4e0 100644 --- a/server/src/com/cloud/async/dao/AsyncJobDaoImpl.java +++ b/server/src/com/cloud/async/dao/AsyncJobDaoImpl.java @@ -42,17 +42,19 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements private static final Logger s_logger = Logger.getLogger(AsyncJobDaoImpl.class.getName()); private final SearchBuilder pendingAsyncJobSearch; - private final SearchBuilder pendingAsyncJobsSearch; - private final SearchBuilder expiringAsyncJobSearch; - - public AsyncJobDaoImpl() { - pendingAsyncJobSearch = createSearchBuilder(); - pendingAsyncJobSearch.and("instanceType", pendingAsyncJobSearch.entity().getInstanceType(), - SearchCriteria.Op.EQ); - pendingAsyncJobSearch.and("instanceId", pendingAsyncJobSearch.entity().getInstanceId(), - SearchCriteria.Op.EQ); - pendingAsyncJobSearch.and("status", pendingAsyncJobSearch.entity().getStatus(), - SearchCriteria.Op.EQ); + private final SearchBuilder pendingAsyncJobsSearch; + private final SearchBuilder expiringUnfinishedAsyncJobSearch; + private final SearchBuilder expiringCompletedAsyncJobSearch; + + + public AsyncJobDaoImpl() { + pendingAsyncJobSearch = createSearchBuilder(); + pendingAsyncJobSearch.and("instanceType", pendingAsyncJobSearch.entity().getInstanceType(), + SearchCriteria.Op.EQ); + pendingAsyncJobSearch.and("instanceId", pendingAsyncJobSearch.entity().getInstanceId(), + SearchCriteria.Op.EQ); + pendingAsyncJobSearch.and("status", pendingAsyncJobSearch.entity().getStatus(), + SearchCriteria.Op.EQ); pendingAsyncJobSearch.done(); pendingAsyncJobsSearch = createSearchBuilder(); @@ -64,27 +66,36 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements SearchCriteria.Op.EQ); pendingAsyncJobsSearch.done(); - expiringAsyncJobSearch = createSearchBuilder(); - expiringAsyncJobSearch.and("created", expiringAsyncJobSearch.entity().getCreated(), + expiringUnfinishedAsyncJobSearch = createSearchBuilder(); + expiringUnfinishedAsyncJobSearch.and("created", expiringUnfinishedAsyncJobSearch.entity().getCreated(), SearchCriteria.Op.LTEQ); - expiringAsyncJobSearch.done(); - } - - public AsyncJobVO findInstancePendingAsyncJob(String instanceType, long instanceId) { - SearchCriteria sc = pendingAsyncJobSearch.create(); - sc.setParameters("instanceType", instanceType); - sc.setParameters("instanceId", instanceId); - sc.setParameters("status", AsyncJobResult.STATUS_IN_PROGRESS); - - List l = listIncludingRemovedBy(sc); - if(l != null && l.size() > 0) { - if(l.size() > 1) { - s_logger.warn("Instance " + instanceType + "-" + instanceId + " has multiple pending async-job"); - } - - return l.get(0); - } - return null; + expiringUnfinishedAsyncJobSearch.and("completeMsId", expiringUnfinishedAsyncJobSearch.entity().getCompleteMsid(), SearchCriteria.Op.NULL); + expiringUnfinishedAsyncJobSearch.and("jobStatus", expiringUnfinishedAsyncJobSearch.entity().getStatus(), SearchCriteria.Op.EQ); + expiringUnfinishedAsyncJobSearch.done(); + + expiringCompletedAsyncJobSearch = createSearchBuilder(); + expiringCompletedAsyncJobSearch.and("created", expiringCompletedAsyncJobSearch.entity().getCreated(), + SearchCriteria.Op.LTEQ); + expiringCompletedAsyncJobSearch.and("completeMsId", expiringCompletedAsyncJobSearch.entity().getCompleteMsid(), SearchCriteria.Op.NNULL); + expiringCompletedAsyncJobSearch.and("jobStatus", expiringCompletedAsyncJobSearch.entity().getStatus(), SearchCriteria.Op.NEQ); + expiringCompletedAsyncJobSearch.done(); + } + + public AsyncJobVO findInstancePendingAsyncJob(String instanceType, long instanceId) { + SearchCriteria sc = pendingAsyncJobSearch.create(); + sc.setParameters("instanceType", instanceType); + sc.setParameters("instanceId", instanceId); + sc.setParameters("status", AsyncJobResult.STATUS_IN_PROGRESS); + + List l = listIncludingRemovedBy(sc); + if(l != null && l.size() > 0) { + if(l.size() > 1) { + s_logger.warn("Instance " + instanceType + "-" + instanceId + " has multiple pending async-job"); + } + + return l.get(0); + } + return null; } public List findInstancePendingAsyncJobs(AsyncJob.Type instanceType, Long accountId) { @@ -99,9 +110,20 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements return listBy(sc); } - public List getExpiredJobs(Date cutTime, int limit) { - SearchCriteria sc = expiringAsyncJobSearch.create(); + @Override + public List getExpiredUnfinishedJobs(Date cutTime, int limit) { + SearchCriteria sc = expiringUnfinishedAsyncJobSearch.create(); sc.setParameters("created", cutTime); + sc.setParameters("jobStatus", 0); + Filter filter = new Filter(AsyncJobVO.class, "created", true, 0L, (long)limit); + return listIncludingRemovedBy(sc, filter); + } + + @Override + public List getExpiredCompletedJobs(Date cutTime, int limit) { + SearchCriteria sc = expiringCompletedAsyncJobSearch.create(); + sc.setParameters("created", cutTime); + sc.setParameters("jobStatus", 0); Filter filter = new Filter(AsyncJobVO.class, "created", true, 0L, (long)limit); return listIncludingRemovedBy(sc, filter); } From b247ba6b4fc3516c87d193ef5bae34c619db2134 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 24 May 2013 15:21:32 -0700 Subject: [PATCH 135/201] CLOUDSTACK-1974: Dedicate Guest VLAN Range - UI - Infrastructure menu - physical network - Guest - devailView - (1) add new tab "Dedicated VLAN Ranges" that list dedicated Guest VLAN Ranges under the physical network. (2) implement "Dedicate Guest VLAN Range" action. --- ui/scripts/system.js | 92 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 2e23fc40202..32303d3ed0f 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -1085,10 +1085,13 @@ tabFilter: function(args) { var hiddenTabs = []; - if (selectedZoneObj.networktype == 'Basic') + if (selectedZoneObj.networktype == 'Basic') { hiddenTabs.push("network"); - else //selectedZoneObj.networktype == 'Advanced' + hiddenTabs.push("dedicatedGuestVlanRanges"); + } + else { //selectedZoneObj.networktype == 'Advanced' hiddenTabs.push("ipAddresses"); + } return hiddenTabs; }, @@ -2115,7 +2118,90 @@ } } } - } + }, + + dedicatedGuestVlanRanges : { + title: 'Dedicated VLAN Ranges', + listView: { + section: 'dedicatedGuestVlanRanges', + id: 'dedicatedGuestVlanRanges', + fields: { + guestvlanrange: { label: 'VLAN Range(s)' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listDedicatedGuestVlanRanges'), + data: { + physicalnetworkid: args.context.physicalNetworks[0].id + }, + success: function(json) { + var items = json.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange; + args.response.success({ data: items }) + } + }); + }, + actions: { + add: { + label: 'Dedicate VLAN Range', + messages: { + notification: function(args) { + return 'Dedicate VLAN Range'; + } + }, + createForm: { + title: 'Dedicate VLAN Range', + fields: { + vlanrange: { label: 'VLAN Range(s)', validation: { required: true } }, + account: { label: 'label.account', validation: { required: true } }, + domainid: { + label: 'label.domain', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL('listDomains'), + data: { listAll: true }, + success: function(json) { + args.response.success({ + data: $.map(json.listdomainsresponse.domain, function(domain) { + return { + id: domain.id, + description: domain.path + }; + }) + }); + } + }); + } + } + } + }, + action: function(args) { + var data = { + physicalnetworkid: args.context.physicalNetworks[0].id, + vlanrange: args.data.vlanrange, + domainid: args.data.domainid, + account: args.data.account + }; + $.ajax({ + url: createURL('dedicateGuestVlanRange'), + data: data, + success: function(json) { + var item = json.dedicateguestvlanrangeresponse.dedicatedguestvlanrange; + args.response.success({ data: item }); + } + }); + }, + notification: { + poll: function(args) { + args.complete(); + } + } + } + } + } + } } } } From 11a7e46dfb8123b5ca96d34c41f401d91df332fa Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 24 May 2013 15:45:10 -0700 Subject: [PATCH 136/201] CLOUDSTACK-1974: Dedicate Guest VLAN Range - UI - Infrastructure menu - physical network - Guest - Dedicated Guest VLAN Range tab - implement Release Dedicated VLAN Range action. --- ui/scripts/system.js | 67 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 32303d3ed0f..8b56bda08e5 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2199,6 +2199,73 @@ } } } + }, + + //??? + detailView: { + name: 'VLAN Range details', + actions: { + remove: { + label: 'Delete VLAN Range', + messages: { + confirm: function(args) { + return 'Please confirm you want to delete VLAN Range'; + }, + notification: function(args) { + return 'Delete VLAN Range'; + } + }, + action: function(args) { + var data = { + id: args.context.dedicatedGuestVlanRanges[0].id + }; + $.ajax({ + url: createURL('releaseDedicatedGuestVlanRange'), + data: data, + async: true, + success: function(json) { + var jid = json.releasededicatedguestvlanrangeresponse.jobid; + args.response.success( + { + _custom: { jobId: jid } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + tabs: { + details: { + title: 'label.details', + fields: [ + { + guestvlanrange: { label: 'VLAN Range(s)' }, + }, + { + domain: { label: 'label.domain' }, + account: { label: 'label.account' }, + id: { label: 'label.id' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listDedicatedGuestVlanRanges'), + data: { + id: args.context.dedicatedGuestVlanRanges[0].id + }, + success: function(json) { + var item = json.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange[0]; + args.response.success({ data: item }) + } + }); + } + } + } } } } From 7cc1e82210f12a615f1f3b425e8076a33ab471e1 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 24 May 2013 16:17:39 -0700 Subject: [PATCH 137/201] CLOUDSTACK-1974: Dedicate Guest VLAN Range - UI - Infrastructure menu - physical network - Guest - Release Dedicated VLAN Range action - change label and message. --- ui/scripts/system.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 8b56bda08e5..ebf173b6ed5 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2200,19 +2200,18 @@ } } }, - - //??? + detailView: { name: 'VLAN Range details', actions: { remove: { - label: 'Delete VLAN Range', + label: 'Release dedicated VLAN range', messages: { confirm: function(args) { - return 'Please confirm you want to delete VLAN Range'; + return 'Please confirm you want to release dedicated VLAN range'; }, notification: function(args) { - return 'Delete VLAN Range'; + return 'Release dedicated VLAN range'; } }, action: function(args) { From d99fae07c7ee750452e346e69f582f0342280f2a Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 24 May 2013 16:36:45 -0700 Subject: [PATCH 138/201] CLOUDSTACK-747: Infrastructure menu - service providers - change display name of internalLbVm to be Internal LB VM. --- ui/scripts/system.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index ebf173b6ed5..9ac3b3083db 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -12706,7 +12706,7 @@ nspHardcodingArray.push( { id: 'InternalLbVm', - name: 'InternalLbVm', + name: 'Internal LB VM', state: nspMap.InternalLbVm ? nspMap.InternalLbVm.state : 'Disabled' } ); From a1437ae82e9c686139c85ac9d3eb039bf968c014 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Fri, 24 May 2013 16:45:15 -0700 Subject: [PATCH 139/201] CLOUDSTACK-2563: Network ACL: Allow protocol 1(icmp) paired with icmp type/code --- .../api/command/user/network/CreateNetworkACLCmd.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index 275fa1866b6..3a56fe4642a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -31,6 +31,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import com.cloud.async.AsyncJob; @@ -98,7 +99,15 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { // /////////////////////////////////////////////////// public String getProtocol() { - return protocol.trim(); + String p = protocol.trim(); + // Deal with ICMP(protocol number 1) specially because it need to be paired with icmp type and code + if(StringUtils.isNumeric(p)){ + int protoNumber = Integer.parseInt(p); + if (protoNumber == 1) { + p = "icmp"; + } + } + return p; } public List getSourceCidrList() { From e3a32867586bbcebe04b009755bfcc116eb1a296 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Fri, 24 May 2013 17:08:31 -0700 Subject: [PATCH 140/201] CLOUDSTACK-2681: Suppress failed to apply port forwarding rule error when rollback --- .../command/user/firewall/CreatePortForwardingRuleCmd.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index 40128526ce0..549de76f2c6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -198,7 +198,11 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P _firewallService.revokeRelatedFirewallRule(getEntityId(), true); } - _rulesService.revokePortForwardingRule(getEntityId(), true); + try { + _rulesService.revokePortForwardingRule(getEntityId(), true); + } catch (Exception ex){ + //Ignore e.g. failed to apply rules to device error + } throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to apply port forwarding rule"); } From a21a4e5ac43af0f225b6e56e3e73ea7e570510d9 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Fri, 24 May 2013 17:10:55 -0700 Subject: [PATCH 141/201] CLOUDSTACK-2682: Sleep 1 second before switch to BACKUP To prevent backup.sh preempt master.sh when keepalived switch to MASTER then back to BACKUP immediately. Since it would take at least 3 seconds for BACKUP to switch to MASTER(vrrp timeout), the fix won't cause chaos when keepalive try to switch to MASTER. --- .../debian/config/root/redundant_router/backup.sh.templ | 2 ++ 1 file changed, 2 insertions(+) diff --git a/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ b/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ index 7a1bd44584a..32c811b26d4 100644 --- a/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ +++ b/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ @@ -16,6 +16,8 @@ # specific language governing permissions and limitations # under the License. +sleep 1 + source /root/func.sh lock="biglock" From a4356b559cb1401c790e1aa62606c1f256e75229 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sat, 25 May 2013 15:03:56 +0530 Subject: [PATCH 142/201] More fixes to regression tests: - Remove extraneous non-ascii chars - cloudconnection is auto GCed. No explicit cleanup required. - Add environment tags for shared network tests - Invalid account.account references - Indentation errors - Skip the storage motion test on unsuitable host environment - remove copy template test. covered in the smoke tests - invalid keys in service dictionary - Unskipping tests skipped tests - Signed-off-by: Prasanna Santhanam --- .../component/test_custom_hostname.py | 2 +- .../component/test_high_availability.py | 1 - .../component/test_host_high_availability.py | 2 +- .../component/test_project_limits.py | 8 +- .../component/test_project_resources.py | 4 +- .../component/test_project_usage.py | 2 +- .../component/test_shared_networks.py | 13 +++ .../component/test_storage_motion.py | 2 - test/integration/component/test_tags.py | 2 +- test/integration/component/test_templates.py | 89 ------------------- .../component/test_vm_passwdenabled.py | 4 +- .../component/test_vpc_network_lbrules.py | 15 ---- .../component/test_vpc_network_pfrules.py | 8 -- .../test_vpc_network_staticnatrule.py | 4 - 14 files changed, 25 insertions(+), 131 deletions(-) diff --git a/test/integration/component/test_custom_hostname.py b/test/integration/component/test_custom_hostname.py index e5452141d9c..a85f619fc00 100644 --- a/test/integration/component/test_custom_hostname.py +++ b/test/integration/component/test_custom_hostname.py @@ -104,7 +104,7 @@ class TestInstanceNameFlagTrue(cloudstackTestCase): cls.services = Services().services # Get Zone, default template cls.zone = get_zone(cls.api_client, cls.services) - cls.services["mode"] = cls.zone.networktype + cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_high_availability.py b/test/integration/component/test_high_availability.py index cd2dfcea559..7b0f78e2446 100644 --- a/test/integration/component/test_high_availability.py +++ b/test/integration/component/test_high_availability.py @@ -169,7 +169,6 @@ class TestHighAvailability(cloudstackTestCase): try: #Clean up, terminate the created accounts, domains etc cleanup_resources(self.apiclient, self.cleanup) - self.testClient.close() except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return diff --git a/test/integration/component/test_host_high_availability.py b/test/integration/component/test_host_high_availability.py index 8c66d175dd7..7a1ad69c7f5 100644 --- a/test/integration/component/test_host_high_availability.py +++ b/test/integration/component/test_host_high_availability.py @@ -156,7 +156,7 @@ class TestHostHighAvailability(cloudstackTestCase): """ Test VM deployments (Create HA enabled Compute Service Offering and VM) """ # Steps, - #1. Create a Compute service offering with the “Offer HA” option selected. + #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. # Validations, #1. Ensure that the offering is created and that in the UI the “Offer HA” field is enabled (Yes) diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 9184dca5202..af99717ad16 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -201,8 +201,8 @@ class TestProjectLimits(cloudstackTestCase): project = Project.create( self.apiclient, self.services["project"], - account=self.admin.account.name, - domainid=self.admin.account.domainid + account=self.admin.name, + domainid=self.admin.domainid ) # Cleanup created project at end of test self.cleanup.append(project) @@ -343,8 +343,8 @@ class TestProjectLimits(cloudstackTestCase): project = Project.create( self.apiclient, self.services["project"], - account=self.admin.account.name, - domainid=self.admin.account.domainid + account=self.admin.name, + domainid=self.admin.domainid ) # Cleanup created project at end of test self.cleanup.append(project) diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index 84141889f3f..378238e70fd 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -651,9 +651,9 @@ class TestTemplates(cloudstackTestCase): """Test use of private template in a project """ # 1. Create a project - # 2. Verify that in order to use somebody’s Private template for vm + # 2. Verify that in order to use somebody's Private template for vm # creation in the project, permission to use the template has to - # be granted to the Project (use API “updateTemplatePermissions” + # be granted to the Project (use API 'updateTemplatePermissions' # with project id to achieve that). self.debug("Deploying VM for with public template: %s" % diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index ab789e1c13d..bb253e1c04a 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -124,7 +124,7 @@ class TestVmUsage(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = cls.cls.zone.networktype + cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, diff --git a/test/integration/component/test_shared_networks.py b/test/integration/component/test_shared_networks.py index 9845826bea6..5f964190356 100644 --- a/test/integration/component/test_shared_networks.py +++ b/test/integration/component/test_shared_networks.py @@ -235,6 +235,7 @@ class TestSharedNetworks(cloudstackTestCase): raise Exception("Warning: Exception during network cleanup : %s" % e) return + @attr(tags=["advanced", "advancedns"]) def test_sharedNetworkOffering_01(self): """ Test shared network Offering 01 """ @@ -372,6 +373,7 @@ class TestSharedNetworks(cloudstackTestCase): ) self.debug("NetworkOffering created and enabled: %s" % self.shared_network_offering.id) + @attr(tags=["advanced", "advancedns"]) def test_sharedNetworkOffering_02(self): """ Test Shared Network Offering 02 """ @@ -459,6 +461,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network Offering creation failed with vlan as False in advance mode and shared guest type.") + @attr(tags=["advanced", "advancedns"]) def test_sharedNetworkOffering_03(self): """ Test Shared Network Offering 03 """ @@ -547,6 +550,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network Offering creation failed with vlan as true and ip ranges as False in advance mode and with shared guest type.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_All(self): """ Test Shared Network ALL """ @@ -829,6 +833,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_accountSpecific(self): """ Test Shared Networm with scope account """ @@ -1092,6 +1097,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_domainSpecific(self): """ Test Shared Network with scope domain """ @@ -1446,6 +1452,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_projectSpecific(self): """ Test Shared Network with scope project """ @@ -1740,6 +1747,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_usedVlan(self): """ Test Shared Network with used vlan 01 """ @@ -1898,6 +1906,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network creation failed because the valn id being used by another network.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_usedVlan2(self): """ Test Shared Network with used vlan 02 """ @@ -2093,6 +2102,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network creation failed because the valn id being used by another network.") + @attr(tags=["advanced", "advancedns"]) def test_deployVM_multipleSharedNetwork(self): """ Test Vm deployment with multiple shared networks """ @@ -2350,6 +2360,7 @@ class TestSharedNetworks(cloudstackTestCase): self.assertTrue(self.network1_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") + @attr(tags=["advanced", "advancedns"]) def test_deployVM_isolatedAndShared(self): """ Test VM deployment in shared and isolated networks """ @@ -2697,6 +2708,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.fail("SSH Access failed for %s: %s" % (self.isolated_network_admin_account_virtual_machine.ipaddress, e)) + @attr(tags=["advanced", "advancedns"]) def test_networkWithsubdomainaccessTrue(self): """ Test Shared Network with subdomainaccess=True """ @@ -2841,6 +2853,7 @@ class TestSharedNetworks(cloudstackTestCase): except: self.debug("Network creation failed because subdomainaccess parameter was passed when scope was account.") + @attr(tags=["advanced", "advancedns"]) def test_networkWithsubdomainaccessFalse(self): """ Test shared Network with subdomainaccess=False """ diff --git a/test/integration/component/test_storage_motion.py b/test/integration/component/test_storage_motion.py index cf110d34e61..0dcc7f8e8d1 100644 --- a/test/integration/component/test_storage_motion.py +++ b/test/integration/component/test_storage_motion.py @@ -178,8 +178,6 @@ class TestStorageMotion(cloudstackTestCase): # Migrate to a host that requires storage motion hosts[:] = [host for host in hosts if host.requiresStorageMotion] - self.assert_(hosts is not None, msg="No valid hosts for storage motion") - self.assert_(len(hosts)>0, msg="No valid hosts for storage motion. Skipping") if hosts is None or len(hosts) == 0: self.skipTest("No valid hosts for storage motion. Skipping") diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 12a586313f1..514c2f7bc96 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -216,7 +216,7 @@ class TestResourceTags(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.zone.networktype ) diff --git a/test/integration/component/test_templates.py b/test/integration/component/test_templates.py index 1a60123b820..65beabfc98f 100644 --- a/test/integration/component/test_templates.py +++ b/test/integration/component/test_templates.py @@ -93,7 +93,6 @@ class Services: "templatefilter": 'self', }, "templatefilter": 'self', - "destzoneid": 2, # For Copy template (Destination zone) "ostype": 'CentOS 5.3 (64-bit)', "sleep": 60, "timeout": 10, @@ -423,94 +422,6 @@ class TestTemplates(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "multizone"]) - def test_02_copy_template(self): - """Test for copy template from one zone to another""" - - # Validate the following - # 1. copy template should be successful and - # secondary storage should contain new copied template. - - self.debug( - "Copying template from zone: %s to %s" % ( - self.template.id, - self.services["destzoneid"] - )) - cmd = copyTemplate.copyTemplateCmd() - cmd.id = self.template.id - cmd.destzoneid = self.services["destzoneid"] - cmd.sourcezoneid = self.zone.id - self.apiclient.copyTemplate(cmd) - - # Verify template is copied to another zone using ListTemplates - list_template_response = list_templates( - self.apiclient, - templatefilter=\ - self.services["templatefilter"], - id=self.template.id, - zoneid=self.services["destzoneid"] - ) - self.assertEqual( - isinstance(list_template_response, list), - True, - "Check for list template response return valid list" - ) - - self.assertNotEqual( - len(list_template_response), - 0, - "Check template extracted in List Templates" - ) - - template_response = list_template_response[0] - self.assertEqual( - template_response.id, - self.template.id, - "Check ID of the downloaded template" - ) - self.assertEqual( - template_response.zoneid, - self.services["destzoneid"], - "Check zone ID of the copied template" - ) - - # Cleanup- Delete the copied template - timeout = self.services["timeout"] - while True: - time.sleep(self.services["sleep"]) - list_template_response = list_templates( - self.apiclient, - templatefilter=\ - self.services["templatefilter"], - id=self.template_2.id, - zoneid=self.services["destzoneid"] - ) - self.assertEqual( - isinstance(list_template_response, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - len(list_template_response), - 0, - "Check template extracted in List Templates" - ) - - template_response = list_template_response[0] - if template_response.isready == True: - break - - if timeout == 0: - raise Exception( - "Failed to download copied template(ID: %s)" % template_response.id) - - timeout = timeout - 1 - cmd = deleteTemplate.deleteTemplateCmd() - cmd.id = self.template.id - cmd.zoneid = self.services["destzoneid"] - self.apiclient.deleteTemplate(cmd) - return - @attr(tags = ["advanced", "advancedns"]) def test_03_delete_template(self): """Test Delete template diff --git a/test/integration/component/test_vm_passwdenabled.py b/test/integration/component/test_vm_passwdenabled.py index e89253c407a..e22a1a0a75a 100644 --- a/test/integration/component/test_vm_passwdenabled.py +++ b/test/integration/component/test_vm_passwdenabled.py @@ -90,8 +90,8 @@ class TestVMPasswordEnabled(cloudstackTestCase): cls.services["ostype"] ) # Set Zones and disk offerings - cls.services["small"]["zoneid"] = zone.id - cls.services["small"]["template"] = template.id + cls.services["service_offerings"]["small"]["zoneid"] = zone.id + cls.services["service_offerings"]["small"]["template"] = template.id # Create VMs, NAT Rules etc cls.account = Account.create( diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py index b4a66070d5b..66d6c4d4018 100644 --- a/test/integration/component/test_vpc_network_lbrules.py +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -505,7 +505,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return nwacl_internet_1 @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_01_VPC_LBRulesListing(self): """ Test case no 210 and 227: List Load Balancing Rules belonging to a VPC """ @@ -551,7 +550,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_02_VPC_LBRulesAndVMListing(self): """ Test case no 211 and 228: List only VMs suitable for the Virtual Network on VPC for LB Rule """ @@ -595,7 +593,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_03_VPC_CreateLBRuleInMultipleNetworks(self): """ Test case no 212 : Create LB rules for 1 network which is part of a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -623,7 +620,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State @@ -651,7 +647,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_05_VPC_CreateAndDeleteLBRule(self): """ Test case no 214 : Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -683,7 +678,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): """ Test case no 224 : Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -715,7 +709,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_07_VPC_CreateAndDeleteAllLBRule(self): """ Test case no 215 : Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -749,7 +742,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): """ Test case no 225 and 226 : Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -783,7 +775,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_09_VPC_LBRuleCreateFailMultipleVPC(self): """ Test case no 234 : User should not be allowed to create a LB rule for a VM that belongs to a different VPC. """ @@ -822,7 +813,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): """ Test case no 216 and 235: User should not be allowed to create a LB rule for a VM that does not belong to any VPC. """ @@ -860,7 +850,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_11_VPC_LBRuleCreateNotAllowed(self): """ Test case no 217 and 236: User should not be allowed to create a LB rule for a VM that does not belong to the same network but belongs to the same VPC. @@ -899,7 +888,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_12_VPC_LBRuleCreateFailForRouterIP(self): """ Test case no 218 and 237: User should not be allowed to create a LB rule on an Ipaddress that Source Nat enabled. """ @@ -928,7 +916,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): """ Test case no 219 : User should not be allowed to create a LB rule on an Ipaddress that already has a PF rule. """ @@ -959,7 +946,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): """ Test case no 220 : User should not be allowed to create a LB rule on an Ipaddress that already has a Static Nat rule. """ @@ -990,7 +976,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_15_VPC_RleaseIPForLBRuleCreated(self): """ Test case no 221 : Release Ip address that has a LB rule assigned to it. """ diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py index 56792f49d00..c0c2b86426c 100644 --- a/test/integration/component/test_vpc_network_pfrules.py +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -553,7 +553,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_03_network_services_VPC_StopCreateMultiplePF(self): """ Test case no 205 : Create PF rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Stopped State @@ -587,7 +586,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_04_network_services_VPC_CreateMultiplePF(self): """ Test case no 191 : Create PF rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Running State @@ -620,7 +618,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_05_network_services_VPC_StopDeletePF(self): """ Test case no 207 : Delete few(not all) PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Stopped State @@ -654,7 +651,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_06_network_services_VPC_DeletePF(self): """ Test case no 193 : Delete few(not all) PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Running State @@ -684,7 +680,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_07_network_services_VPC_StopDeleteAllPF(self): """ Test case no 208 : Delete all PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Stopped State @@ -721,7 +716,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_08_network_services_VPC_DeleteAllPF(self): """ Test case no 194 : Delete all PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Running State @@ -754,7 +748,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): """ Test case no 209 : Delete all PF rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when Virtual Router is in Stopped State @@ -817,7 +810,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_10_network_services_VPC_DeleteAllMultiplePF(self): """ Test case no 195: Delete all PF rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when Virtual Router is in Running State diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py index aceca62d1fb..bed1b5298b3 100644 --- a/test/integration/component/test_vpc_network_staticnatrule.py +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -552,7 +552,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): """ Test case no extra : Create Static Nat Rule rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Stopped State @@ -586,7 +585,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_04_VPC_CreateMultipleStaticNatRule(self): """ Test case no 230 : Create Static NAT Rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -619,7 +617,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_05_network_services_VPC_DeleteAllPF(self): """ Test case no 232: Delete all Static NAT Rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -651,7 +648,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_06_network_services_VPC_DeleteAllMultiplePF(self): """ Test case no 233: Delete all Static NAT rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when the Virtual Router is in Running State. From 056e8fb533db72cc052dd67fbd0389f921b38471 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Sat, 25 May 2013 20:32:10 +0530 Subject: [PATCH 143/201] cli: Make cachemaker.py pep8 compliant Fixes object comparision to use a "is" b instead of == Signed-off-by: Rohit Yadav --- tools/cli/cloudmonkey/cachemaker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cli/cloudmonkey/cachemaker.py b/tools/cli/cloudmonkey/cachemaker.py index a625b014d38..47749e5ae74 100644 --- a/tools/cli/cloudmonkey/cachemaker.py +++ b/tools/cli/cloudmonkey/cachemaker.py @@ -101,7 +101,7 @@ def monkeycache(apis): cache['asyncapis'] = [] apilist = getvalue(apis[responsekey], 'api') - if apilist == None: + if apilist is None: print "[monkeycache] Server response issue, no apis found" for api in apilist: From 51879dd9585f548c2c42b5a7bcc87e88c1caf0fa Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Sat, 25 May 2013 20:44:05 +0530 Subject: [PATCH 144/201] INSTALL: Update INSTALL.md with newer links - Fix Maven 3.0.5 link - Remove references of incubating, we are TLP now :) - Fix github mirror link and git clone url Signed-off-by: Rohit Yadav --- INSTALL.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 4f93900ddfe..b0e1a7617b0 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,5 +1,5 @@ -This document describes how to develop, build, package and install Apache CloudStack -(Incubating). For more information please refer to the project's website: +This document describes how to develop, build, package and install Apache +CloudStack. For more information please refer to: http://cloudstack.apache.org @@ -10,7 +10,7 @@ Refer to the [wiki](http://cwiki.apache.org/confluence/display/CLOUDSTACK/Index) for the latest information, especially: - [Setting up development environment](https://cwiki.apache.org/confluence/display/CLOUDSTACK/Setting+up+CloudStack+Development+Environment) for Apache CloudStack. - - [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/Building) Apache CloudStack. + - [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/How+to+build+on+master+branch) Apache CloudStack. ## Setting up Development Environment @@ -21,12 +21,12 @@ Install tools and dependencies used for development: $ yum install git ant ant-devel java-1.6.0-openjdk java-1.6.0-openjdk-devel mysql mysql-server tomcat6 mkisofs gcc python MySQL-python openssh-clients wget -Set up Maven (3.0.4): +Set up Maven (3.0.5): - $ wget http://www.us.apache.org/dist/maven/maven-3/3.0.4/binaries/apache-maven-3.0.4-bin.tar.gz + $ wget http://www.us.apache.org/dist/maven/maven-3/3.0.5/binaries/apache-maven-3.0.5-bin.tar.gz $ cd /usr/local/ # or any path - $ tar -zxvf apache-maven-3.0.4-bin.tar.gz - $ echo export M2_HOME=/usr/local/apache-maven-3.0.4 >> ~/.bashrc # or .zshrc or .profile + $ tar -zxvf apache-maven-3.0.5-bin.tar.gz + $ echo export M2_HOME=/usr/local/apache-maven-3.0.5 >> ~/.bashrc # or .zshrc or .profile $ echo export PATH=${M2_HOME}/bin:${PATH} >> ~/.bashrc # or .zshrc or .profile Note: Tomcat 6.0.35 has some known issue with Apache CloudStack, please use Tomcat @@ -77,10 +77,10 @@ Start the MySQL service: You may get the source code from the repository hosted on Apache: - $ git clone https://git-wip-us.apache.org/repos/asf/cloudstack.git + $ git clone git://git.apache.org/cloudstack.git Or, you may fork a repository from the official Apache CloudStack mirror by -Apache on [Github](https://github.com/apache/incubator-cloudstack) +Apache on [Github](https://github.com/apache/cloudstack) To keep yourself updated on a branch, do: @@ -92,7 +92,6 @@ For example, for master: ## Building - Clean and build: $ mvn clean install -P systemvm,developer From dc822a83d77830281402175b4a57b25b7e3b180a Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Sun, 26 May 2013 00:37:16 +0900 Subject: [PATCH 145/201] fix debian packaging *.in files must be processed by ReplaceTokens fliter. Signed-off-by: Hiroaki KAWAI --- debian/rules | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/rules b/debian/rules index 48485bb9d9b..e5ff5484fe5 100755 --- a/debian/rules +++ b/debian/rules @@ -69,8 +69,8 @@ install: install -D plugins/hypervisors/kvm/target/cloud-plugin-hypervisor-kvm-$(VERSION)-SNAPSHOT.jar $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/ install -D plugins/hypervisors/kvm/target/dependencies/* $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/ install -D packaging/debian/init/cloud-agent $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-agent - install -D agent/bindir/cloud-setup-agent.in $(DESTDIR)/usr/bin/cloudstack-setup-agent - install -D agent/bindir/cloud-ssh.in $(DESTDIR)/usr/bin/cloudstack-ssh + install -D agent/target/transformed/cloud-setup-agent $(DESTDIR)/usr/bin/cloudstack-setup-agent + install -D agent/target/transformed/cloud-ssh $(DESTDIR)/usr/bin/cloudstack-ssh install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent # cloudstack-management @@ -102,7 +102,7 @@ install: ln -s tomcat6-nonssl.conf $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/tomcat6.conf ln -s server-nonssl.xml $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/server.xml install -D packaging/debian/init/cloud-management $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-management - install -D client/bindir/cloud-update-xenserver-licenses.in $(DESTDIR)/usr/bin/cloudstack-update-xenserver-licenses + install -D client/target/utilities/bin/cloud-update-xenserver-licenses $(DESTDIR)/usr/bin/cloudstack-update-xenserver-licenses ln -s /usr/share/tomcat6/bin $(DESTDIR)/usr/share/$(PACKAGE)-management/bin # Remove configuration in /ur/share/cloudstack-management/webapps/client/WEB-INF # This should all be in /etc/cloudstack/management From 5b902c700513423921da48161acd7f8cff8a0b56 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sun, 26 May 2013 14:46:27 +0530 Subject: [PATCH 146/201] CLOUDSTACK-2683: DevCloud systemVMs fail to launch DevCloud is a XCP Kronos based xen. For this we use the XcpOssResource whose memory limits were not set explicitly. Instead the base CitrixResourceBase would set the limits. static_min was set to 128MB failing the cpvm and ssvm start fails whose offerings have 100MB set to the max limits. Signed-off-by: Prasanna Santhanam --- .../xen/resource/XcpOssResource.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java index 357b4333678..870049c8111 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java @@ -17,17 +17,6 @@ package com.cloud.hypervisor.xen.resource; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; - -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkUsageAnswer; @@ -46,14 +35,24 @@ import com.cloud.utils.script.Script; import com.cloud.vm.VirtualMachine; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; -import com.xensource.xenapi.Types.XenAPIException; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import javax.ejb.Local; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; @Local(value=ServerResource.class) public class XcpOssResource extends CitrixResourceBase { - private final static Logger s_logger = Logger.getLogger(XcpServerResource.class); + private final static Logger s_logger = Logger.getLogger(XcpOssResource.class); + private static final long mem_32m = 33554432L; + @Override protected List getPatchFiles() { List files = new ArrayList(); @@ -167,4 +166,9 @@ public class XcpOssResource extends CitrixResourceBase { } return answer; } + + @Override + protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); + } } From 322db71eedb6b52fca6f92b46b613607083c4d88 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Sun, 26 May 2013 11:38:00 +0200 Subject: [PATCH 147/201] agent: Only probe running VMs for the current Hypervisor Type Otherwise we try to probe for LXC VMs on a KVM hypervisor and vise versa. --- agent/conf/agent.properties | 5 ++++ .../resource/LibvirtComputingResource.java | 24 +++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index 7dc4ba8a18c..60030ae4f11 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -84,6 +84,11 @@ domr.scripts.dir=scripts/network/domr/kvm # set the hypervisor type, values are: kvm, lxc # hypervisor.type=kvm +# set the hypervisor URI. Usually there is no need for changing this +# For KVM: qemu:///system +# For LXC: lxc:/// +# hypervisor.uri=qemu:///system + # settings to enable direct networking in libvirt, should not be used # on hosts that run system vms, values for mode are: private, bridge, vepa # libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.DirectVifDriver diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index c34d1eb1821..f979cfe00e4 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -3943,18 +3943,22 @@ ServerResource { final HashMap vmStates = new HashMap(); Connect conn = null; - try { - conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString()); - vmStates.putAll(getAllVms(conn)); - } catch (LibvirtException e) { - s_logger.debug("Failed to get connection: " + e.getMessage()); + if (_hypervisorType == HypervisorType.LXC) { + try { + conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString()); + vmStates.putAll(getAllVms(conn)); + } catch (LibvirtException e) { + s_logger.debug("Failed to get connection: " + e.getMessage()); + } } - try { - conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString()); - vmStates.putAll(getAllVms(conn)); - } catch (LibvirtException e) { - s_logger.debug("Failed to get connection: " + e.getMessage()); + if (_hypervisorType == HypervisorType.KVM) { + try { + conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString()); + vmStates.putAll(getAllVms(conn)); + } catch (LibvirtException e) { + s_logger.debug("Failed to get connection: " + e.getMessage()); + } } return vmStates; From 1df3aad9abf4c64d8d64e569389144374a1d4f27 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sun, 26 May 2013 15:25:33 +0530 Subject: [PATCH 148/201] Use a dummy ISO and skip SSH check - Using the dummy.iso to speed up the test - Removing ssh that is not required. Signed-off-by: Prasanna Santhanam --- test/integration/component/test_stopped_vm.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test/integration/component/test_stopped_vm.py b/test/integration/component/test_stopped_vm.py index f1096919824..0527b3d7ebf 100644 --- a/test/integration/component/test_stopped_vm.py +++ b/test/integration/component/test_stopped_vm.py @@ -78,7 +78,7 @@ class Services: { "displaytext": "Test ISO", "name": "testISO", - "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + "url": "http://people.apache.org/~tsp/dummy.iso", # Source URL where ISO is located "ostype": 'CentOS 5.3 (64-bit)', "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO @@ -219,10 +219,6 @@ class TestDeployVM(cloudstackTestCase): "Running", "VM should be in Running state after deployment" ) - try: - ssh = self.virtual_machine.get_ssh_client() - except Exception as e: - self.fail("SSH to VM instance failed!") return @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) @@ -274,10 +270,6 @@ class TestDeployVM(cloudstackTestCase): "Running", "VM should be in Running state after deployment" ) - try: - ssh = self.virtual_machine.get_ssh_client() - except Exception as e: - self.fail("SSH to VM instance failed!") return @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) From f13a3c5d32de020e3da6456b2dbb79b9112b24b5 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sun, 26 May 2013 15:29:45 +0530 Subject: [PATCH 149/201] More tests using the dsl iso Replace dsl iso with dummy iso to speed up test Signed-off-by: Prasanna Santhanam --- test/integration/component/test_tags.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 514c2f7bc96..992ca1daf58 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -102,9 +102,9 @@ class Services: }, "iso": { - "displaytext": "DSL ISO", - "name": "DSL ISO", - "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + "displaytext": "Dummy ISO", + "name": "Dummy ISO", + "url": "http://people.apache.org/~tsp/dummy.iso", # Source URL where ISO is located "isextractable": True, "isfeatured": True, From 2db7a4559e64e34b5c707157db240a1be322cb69 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Sun, 26 May 2013 11:55:53 +0200 Subject: [PATCH 150/201] debian: Only package specified configuration files for management Otherwise we will have duplicate / conflicting files with the AWSAPI package --- debian/cloudstack-management.install | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install index 5a682d45862..2cc3e925970 100644 --- a/debian/cloudstack-management.install +++ b/debian/cloudstack-management.install @@ -15,7 +15,26 @@ # specific language governing permissions and limitations # under the License. -/etc/cloudstack/management/* +/etc/cloudstack/management/server-ssl.xml +/etc/cloudstack/management/catalina.policy +/etc/cloudstack/management/catalina.properties +/etc/cloudstack/management/cloudmanagementserver.keystore +/etc/cloudstack/management/logging.properties +/etc/cloudstack/management/commands.properties +/etc/cloudstack/management/ehcache.xml +/etc/cloudstack/management/tomcat6-nonssl.conf +/etc/cloudstack/management/componentContext.xml +/etc/cloudstack/management/applicationContext.xml +/etc/cloudstack/management/server-nonssl.xml +/etc/cloudstack/management/classpath.conf +/etc/cloudstack/management/db.properties +/etc/cloudstack/management/tomcat6-ssl.conf +/etc/cloudstack/management/web.xml +/etc/cloudstack/management/environment.properties +/etc/cloudstack/management/nonossComponentContext.xml +/etc/cloudstack/management/log4j-cloud.xml +/etc/cloudstack/management/tomcat-users.xml +/etc/cloudstack/management/context.xml /etc/init.d/cloudstack-management /etc/security/limits.d/cloudstack-limits.conf /etc/sudoers.d/cloudstack From a4a50a0b538ba2fcb71deed26a6d22d527ac457d Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sun, 26 May 2013 15:31:33 +0530 Subject: [PATCH 151/201] Remove unused setup script - All the setup is now done by the tests and there is no need for a setup script to seed test data. Signed-off-by: Prasanna Santhanam --- test/setup-test-data.sh | 102 ---------------------------------------- 1 file changed, 102 deletions(-) delete mode 100755 test/setup-test-data.sh diff --git a/test/setup-test-data.sh b/test/setup-test-data.sh deleted file mode 100755 index 844c275da7c..00000000000 --- a/test/setup-test-data.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/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 -# 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. - -usage() { - printf "Usage: %s:\n - [-t path to tests ] \n - [-m mgmt-server ] \n - [-h hypervisor (xen|kvm) ] \n - [-p hypervisor root password ] \n - [-d db node url ]\n" $(basename $0) >&2 -} - -failed() { - exit $1 -} - -#defaults -TESTDIR="/root/cloudstack/test/" -MGMT_SVR="localhost" -DB_SVR="localhost" -HV_PASSWD="password" - -while getopts 't:d:m:p:h:' OPTION -do - case $OPTION in - d) dflag=1 - DB_SVR="$OPTARG" - ;; - t) tflag=1 - TESTDIR="$OPTARG" - ;; - m) mflag=1 - MGMT_SVR="$OPTARG" - ;; - h) hflag=1 - HV="$OPTARG" - ;; - p) pflag=1 - HV_PASSWD="$OPTARG" - ;; - ?) usage - failed 2 - ;; - esac -done - -#Damn Small Linux ISO type -if [[ $HV == "kvm" ]]; then - ostypeid=$(mysql -ucloud -Dcloud -pcloud -h$DB_SVR -s -N -r -e"select uuid from guest_os where display_name='CentOS 5.5 (64-bit)'") -else - ostypeid=$(mysql -ucloud -Dcloud -pcloud -h$DB_SVR -s -N -r -e"select uuid from guest_os where display_name='CentOS 5.3 (64-bit)'") -fi -if [[ $ostypeid == "" ]]; then - echo "Unable to contact DB server @ $DB_SVR" - exit 2 -fi - -nc -z $MGMT_SVR 8096 -if [[ $? -ne 0 ]]; then - echo "$MGMT_SVR doesn't have port 8096 open" - exit 2 -fi - -if [[ ! -d $TESTDIR ]]; then - echo "No directory $TESTDIR found" - exit 2 -fi -for file in `find $TESTDIR -name *.py -type f` -do - old_ostypeid=$(grep ostypeid $file | head -1 | cut -d: -f2 | tr -d " ,'") - if [[ $old_ostypeid != "" ]] - then - echo "replacing:" $old_ostypeid, "with:" $ostypeid,"in " $file - sed -i "s/$old_ostypeid/$ostypeid/g" $file - #sed -i "s/http:\/\/iso.linuxquestions.org\/download\/504\/1819\/http\/gd4.tuwien.ac.at\/dsl-4.4.10.iso/http:\/\/nfs1.lab.vmops.com\/isos_32bit\/dsl-4.4.10.iso/g" $file - sed -i "s/fr3sca/$HV_PASSWD/g" $file - fi -done - -#Python version check -version_tuple=$(python -c 'import sys; print(sys.version_info[:2])') -if [[ $version_tuple == "(2, 7)" ]] -then - echo "Done" -else - echo "WARN: Python version 2.7 not detected on system." -fi From 61e150fd58547e5a02522c7e40e1091b59fea10c Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sun, 26 May 2013 20:10:46 +0530 Subject: [PATCH 152/201] More non-ascii encoded characters in commented text Signed-off-by: Prasanna Santhanam --- .../component/test_host_high_availability.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/integration/component/test_host_high_availability.py b/test/integration/component/test_host_high_availability.py index 7a1ad69c7f5..ec297d43427 100644 --- a/test/integration/component/test_host_high_availability.py +++ b/test/integration/component/test_host_high_availability.py @@ -159,10 +159,10 @@ class TestHostHighAvailability(cloudstackTestCase): #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. # Validations, - #1. Ensure that the offering is created and that in the UI the “Offer HA” field is enabled (Yes) - #The listServiceOffering API should list “offerha” as true. + #1. Ensure that the offering is created and that in the UI the 'Offer HA' field is enabled (Yes) + #The listServiceOffering API should list 'offerha' as true. #2. Select the newly created VM and ensure that the Compute offering field value lists the compute service offering that was selected. - # Also, check that the HA Enabled field is enabled “Yes”. + # Also, check that the HA Enabled field is enabled 'Yes'. #list and validate above created service offering with Ha enabled list_service_response = list_service_offering( @@ -346,12 +346,12 @@ class TestHostHighAvailability(cloudstackTestCase): """ Verify you can not migrate VMs to hosts with an ha.tag (positive) """ # Steps, - #1. Create a Compute service offering with the “Offer HA” option selected. + #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. - #3. Select the VM and migrate VM to another host. Choose a “Suitable” host (i.e. host2) + #3. Select the VM and migrate VM to another host. Choose a 'Suitable' host (i.e. host2) # Validations - #The option from the “Migrate instance to another host” dialog box” should list host3 as “Not Suitable” for migration. - #Confirm that the VM is migrated to the “Suitable” host you selected (i.e. host2) + #The option from the 'Migrate instance to another host' dialog box' should list host3 as 'Not Suitable' for migration. + #Confirm that the VM is migrated to the 'Suitable' host you selected (i.e. host2) #create and verify the virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( @@ -452,11 +452,11 @@ class TestHostHighAvailability(cloudstackTestCase): """ Verify you can not migrate VMs to hosts with an ha.tag (negative) """ # Steps, - #1. Create a Compute service offering with the “Offer HA” option selected. + #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. - #3. Select the VM and migrate VM to another host. Choose a “Not Suitable” host. + #3. Select the VM and migrate VM to another host. Choose a 'Not Suitable' host. # Validations, - #The option from the “Migrate instance to another host” dialog box” should list host3 as “Not Suitable” for migration. + #The option from the 'Migrate instance to another host' dialog box should list host3 as 'Not Suitable' for migration. #By design, The Guest VM can STILL can be migrated to host3 if the admin chooses to do so. #create and verify virtual machine with HA enabled service offering @@ -558,11 +558,11 @@ class TestHostHighAvailability(cloudstackTestCase): """ Verify that none of the VMs with HA enabled migrate to an ha tagged host during live migration """ # Steps, - #1. Fresh install CS (Bonita) that supports this feature + #1. Fresh install CS that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage #3. When adding host3, assign the HA host tag. #4. Create VMs with and without the Compute Service Offering with the HA tag. - #5. Note the VMs on host1 and whether any of the VMs have their “HA enabled” flags enabled. + #5. Note the VMs on host1 and whether any of the VMs have their 'HA enabled' flags enabled. #6. Put host1 into maintenance mode. # Validations, #1. Make sure the VMs are created on either host1 or host2 and not on host3 @@ -690,11 +690,11 @@ class TestHostHighAvailability(cloudstackTestCase): """ Verify that none of the VMs without HA enabled migrate to an ha tagged host during live migration """ # Steps, - #1. Fresh install CS (Bonita) that supports this feature + #1. Fresh install CS that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage #3. When adding host3, assign the HA host tag. #4. Create VMs with and without the Compute Service Offering with the HA tag. - #5. Note the VMs on host1 and whether any of the VMs have their “HA enabled” flags enabled. + #5. Note the VMs on host1 and whether any of the VMs have their 'HA enabled' flags enabled. #6. Put host1 into maintenance mode. # Validations, #1. Make sure the VMs are created on either host1 or host2 and not on host3 From 16e9eaca80bb4c7fe2baa2ce05fc03a9032277cd Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 27 May 2013 10:10:01 +0530 Subject: [PATCH 153/201] unskipping skipped tests and indentation fixes Signed-off-by: Prasanna Santhanam --- .../component/test_host_high_availability.py | 677 +++++++++--------- .../component/test_vpc_host_maintenance.py | 2 - 2 files changed, 337 insertions(+), 342 deletions(-) diff --git a/test/integration/component/test_host_high_availability.py b/test/integration/component/test_host_high_availability.py index ec297d43427..57eb5edede9 100644 --- a/test/integration/component/test_host_high_availability.py +++ b/test/integration/component/test_host_high_availability.py @@ -18,15 +18,12 @@ """ P1 tests for dedicated Host high availability """ #Import Local Modules -import marvin from nose.plugins.attrib import attr from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * -from marvin import remoteSSHClient -import datetime class Services: @@ -34,90 +31,90 @@ class Services: def __init__(self): self.services = { - "account": { - "email": "test@test.com", - "firstname": "HA", - "lastname": "HA", - "username": "HA", - # Random characters are appended for unique - # username - "password": "password", - }, - "service_offering_with_ha": { - "name": "Tiny Instance With HA Enabled", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "service_offering_without_ha": { - "name": "Tiny Instance Without HA", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "virtual_machine": { - "displayname": "VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - # Hypervisor type should be same as - # hypervisor type of cluster - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "ostype": 'CentOS 5.3 (64-bit)', - "timeout": 100, - } + "account": { + "email": "test@test.com", + "firstname": "HA", + "lastname": "HA", + "username": "HA", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering_with_ha": { + "name": "Tiny Instance With HA Enabled", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "service_offering_without_ha": { + "name": "Tiny Instance Without HA", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "timeout": 100, + } + class TestHostHighAvailability(cloudstackTestCase): """ Dedicated host HA test cases """ - + @classmethod def setUpClass(cls): - cls.api_client = super( - TestHostHighAvailability, - cls - ).getClsTestClient().getApiClient() + TestHostHighAvailability, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain( - cls.api_client, - cls.services - ) + cls.api_client, + cls.services + ) cls.zone = get_zone( - cls.api_client, - cls.services - ) + cls.api_client, + cls.services + ) cls.template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering_with_ha = ServiceOffering.create( - cls.api_client, - cls.services["service_offering_with_ha"], - offerha=True - ) - + cls.api_client, + cls.services["service_offering_with_ha"], + offerha=True + ) + cls.service_offering_without_ha = ServiceOffering.create( - cls.api_client, - cls.services["service_offering_without_ha"], - offerha=False - ) - + cls.api_client, + cls.services["service_offering_without_ha"], + offerha=False + ) + cls._cleanup = [ - cls.service_offering_with_ha, - cls.service_offering_without_ha, - ] + cls.service_offering_with_ha, + cls.service_offering_without_ha, + ] return @classmethod @@ -133,11 +130,11 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.account = Account.create( - self.apiclient, - self.services["account"], - admin=True, - domainid=self.domain.id - ) + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) self.cleanup = [self.account] return @@ -150,11 +147,11 @@ class TestHostHighAvailability(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator"]) + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator"]) def test_01_vm_deployment_with_compute_offering_with_ha_enabled(self): """ Test VM deployments (Create HA enabled Compute Service Offering and VM) """ - + # Steps, #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. @@ -163,63 +160,63 @@ class TestHostHighAvailability(cloudstackTestCase): #The listServiceOffering API should list 'offerha' as true. #2. Select the newly created VM and ensure that the Compute offering field value lists the compute service offering that was selected. # Also, check that the HA Enabled field is enabled 'Yes'. - + #list and validate above created service offering with Ha enabled list_service_response = list_service_offering( - self.apiclient, - id=self.service_offering_with_ha.id - ) + self.apiclient, + id=self.service_offering_with_ha.id + ) self.assertEqual( isinstance(list_service_response, list), True, "listServiceOfferings returned invalid object in response." - ) + ) self.assertNotEqual( len(list_service_response), 0, "listServiceOfferings returned empty list." - ) + ) self.assertEqual( list_service_response[0].offerha, True, "The service offering is not HA enabled" - ) - + ) + #create virtual machine with the service offering with Ha enabled virtual_machine = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine.id, - listall=True - ) + self.apiclient, + id=virtual_machine.id, + listall=True + ) self.assertEqual( isinstance(vms, list), True, "listVirtualMachines returned invalid object in response." - ) + ) self.assertNotEqual( len(vms), 0, "listVirtualMachines returned empty list." - ) + ) self.debug("Deployed VM on host: %s" % vms[0].hostid) self.assertEqual( vms[0].haenable, True, "VM not created with HA enable tag" - ) + ) - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_02_no_vm_creation_on_host_with_haenabled(self): """ Verify you can not create new VMs on hosts with an ha.tag """ - + # Steps, #1. Fresh install CS (Bonita) that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage @@ -229,122 +226,122 @@ class TestHostHighAvailability(cloudstackTestCase): # Validations, #Check to make sure the newly created VM is not on any HA enabled hosts #The VM should be created only on host1 or host2 and never host3 (HA enabled) - + #create and verify virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "listVirtualMachines returned invalid object in response." - ) - + ) + self.assertNotEqual( len(vms), 0, "listVirtualMachines returned empty list." - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #validate the virtual machine created is host Ha enabled list_hosts_response = list_hosts( - self.apiclient, - id=vm.hostid - ) + self.apiclient, + id=vm.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "listHosts returned invalid object in response." - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "listHosts retuned empty list in response." - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "VM created on HA enabled host." - ) - + ) + #create and verify virtual machine with Ha disabled service offering virtual_machine_without_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_without_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_without_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_without_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_without_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "listVirtualMachines returned invalid object in response." - ) - + ) + self.assertNotEqual( len(vms), 0, "listVirtualMachines returned empty list." - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #verify that the virtual machine created on the host is Ha disabled list_hosts_response = list_hosts( - self.apiclient, - id=vm.hostid - ) + self.apiclient, + id=vm.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "listHosts returned invalid object in response." - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "listHosts returned empty list." - ) - + ) + host = list_hosts_response[0] - + self.assertEqual( host.hahost, False, "VM migrated to HA enabled host." - ) + ) - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_03_cant_migrate_vm_to_host_with_ha_positive(self): """ Verify you can not migrate VMs to hosts with an ha.tag (positive) """ - + # Steps, #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. @@ -352,61 +349,61 @@ class TestHostHighAvailability(cloudstackTestCase): # Validations #The option from the 'Migrate instance to another host' dialog box' should list host3 as 'Not Suitable' for migration. #Confirm that the VM is migrated to the 'Suitable' host you selected (i.e. host2) - + #create and verify the virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True, - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True, + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #Find out a Suitable host for VM migration list_hosts_response = list_hosts( - self.apiclient, - ) + self.apiclient, + ) self.assertEqual( isinstance(list_hosts_response, list), True, "The listHosts API returned the invalid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "The listHosts returned nothing." - ) + ) suitableHost = None for host in list_hosts_response: if host.suitableformigration == True and host.hostid != vm.hostid: suitableHost = host break - + self.assertTrue(suitableHost is not None, "suitablehost should not be None") - + #Migration of the VM to a suitable host self.debug("Migrating VM-ID: %s to Host: %s" % (self.vm.id, suitableHost.id)) @@ -417,20 +414,20 @@ class TestHostHighAvailability(cloudstackTestCase): #Verify that the VM migrated to a targeted Suitable host list_vm_response = list_virtual_machines( - self.apiclient, - id=vm.id - ) + self.apiclient, + id=vm.id + ) self.assertEqual( isinstance(list_vm_response, list), True, "The listVirtualMachines returned the invalid list." - ) + ) self.assertNotEqual( list_vm_response, None, "The listVirtualMachines API returned nothing." - ) + ) vm_response = list_vm_response[0] @@ -438,19 +435,19 @@ class TestHostHighAvailability(cloudstackTestCase): vm_response.id, vm.id, "The virtual machine id and the the virtual machine from listVirtualMachines is not matching." - ) + ) self.assertEqual( vm_response.hostid, suitableHost.id, "The VM is not migrated to targeted suitable host." - ) - - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + ) + + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_04_cant_migrate_vm_to_host_with_ha_negative(self): """ Verify you can not migrate VMs to hosts with an ha.tag (negative) """ - + # Steps, #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. @@ -458,62 +455,62 @@ class TestHostHighAvailability(cloudstackTestCase): # Validations, #The option from the 'Migrate instance to another host' dialog box should list host3 as 'Not Suitable' for migration. #By design, The Guest VM can STILL can be migrated to host3 if the admin chooses to do so. - + #create and verify virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "The listVirtualMachines returned invalid object in response." - ) - + ) + self.assertNotEqual( len(vms), 0, "The listVirtualMachines returned empty response." - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #Find out Non-Suitable host for VM migration list_hosts_response = list_hosts( - self.apiclient, - ) + self.apiclient, + ) self.assertEqual( isinstance(list_hosts_response, list), True, "listHosts returned invalid object in response." - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "listHosts returned empty response." - ) - - notSuitableHost = None + ) + + notSuitableHost = None for host in list_hosts_response: if not host.suitableformigration and host.hostid != vm.hostid: notSuitableHost = host - break - + break + self.assertTrue(notSuitableHost is not None, "notsuitablehost should not be None") - + #Migrate VM to Non-Suitable host self.debug("Migrating VM-ID: %s to Host: %s" % (vm.id, notSuitableHost.id)) @@ -524,39 +521,39 @@ class TestHostHighAvailability(cloudstackTestCase): #Verify that the virtual machine got migrated to targeted Non-Suitable host list_vm_response = list_virtual_machines( - self.apiclient, - id=vm.id - ) + self.apiclient, + id=vm.id + ) self.assertEqual( isinstance(list_vm_response, list), True, "listVirtualMachine returned invalid object in response." - ) + ) self.assertNotEqual( len(list_vm_response), 0, "listVirtualMachines returned empty response." - ) + ) self.assertEqual( list_vm_response[0].id, vm.id, "Virtual machine id with the virtual machine from listVirtualMachine is not matching." - ) + ) self.assertEqual( list_vm_response[0].hostid, notSuitableHost.id, "The detination host id of migrated VM is not matching." - ) + ) - @attr(configuration = "ha.tag") - @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + @attr(configuration="ha.tag") + @attr(speed="slow") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_05_no_vm_with_ha_gets_migrated_to_ha_host_in_live_migration(self): """ Verify that none of the VMs with HA enabled migrate to an ha tagged host during live migration """ - + # Steps, #1. Fresh install CS that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage @@ -567,128 +564,128 @@ class TestHostHighAvailability(cloudstackTestCase): # Validations, #1. Make sure the VMs are created on either host1 or host2 and not on host3 #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3. - + # create and verify virtual machine with HA disabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm_with_ha_enabled = vms[0] - + #Verify the virtual machine got created on non HA host list_hosts_response = list_hosts( - self.apiclient, - id=vm_with_ha_enabled.hostid - ) + self.apiclient, + id=vm_with_ha_enabled.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + #put the Host in maintainance mode self.debug("Enabling maintenance mode for host %s" % vm_with_ha_enabled.hostid) cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() cmd.id = vm_with_ha_enabled.hostid self.apiclient.prepareHostForMaintenance(cmd) - + timeout = self.services["timeout"] - + #verify the VM live migration happened to another running host self.debug("Waiting for VM to come up") wait_for_vm( self.apiclient, virtualmachineid=vm_with_ha_enabled.id, interval=timeout - ) - + ) + vms = VirtualMachine.list( - self.apiclient, - id=vm_with_ha_enabled.id, - listall=True, - ) - + self.apiclient, + id=vm_with_ha_enabled.id, + listall=True, + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm_with_ha_enabled1 = vms[0] - + list_hosts_response = list_hosts( - self.apiclient, - id=vm_with_ha_enabled1.hostid - ) + self.apiclient, + id=vm_with_ha_enabled1.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_enabled.hostid) cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() cmd.id = vm_with_ha_enabled.hostid self.apiclient.cancelHostMaintenance(cmd) - - @attr(configuration = "ha.tag") - @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + + @attr(configuration="ha.tag") + @attr(speed="slow") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_06_no_vm_without_ha_gets_migrated_to_ha_host_in_live_migration(self): """ Verify that none of the VMs without HA enabled migrate to an ha tagged host during live migration """ - + # Steps, #1. Fresh install CS that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage @@ -699,115 +696,115 @@ class TestHostHighAvailability(cloudstackTestCase): # Validations, #1. Make sure the VMs are created on either host1 or host2 and not on host3 #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3. - + # create and verify virtual machine with HA disabled service offering virtual_machine_without_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_without_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_without_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_without_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_without_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm_with_ha_disabled = vms[0] - + #Verify the virtual machine got created on non HA host list_hosts_response = list_hosts( - self.apiclient, - id=vm_with_ha_disabled.hostid - ) + self.apiclient, + id=vm_with_ha_disabled.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + #put the Host in maintainance mode self.debug("Enabling maintenance mode for host %s" % vm_with_ha_disabled.hostid) cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() cmd.id = vm_with_ha_disabled.hostid self.apiclient.prepareHostForMaintenance(cmd) - + timeout = self.services["timeout"] - + #verify the VM live migration happened to another running host self.debug("Waiting for VM to come up") wait_for_vm( self.apiclient, virtualmachineid=vm_with_ha_disabled.id, interval=timeout - ) - + ) + vms = VirtualMachine.list( - self.apiclient, - id=vm_with_ha_disabled.id, - listall=True - ) - + self.apiclient, + id=vm_with_ha_disabled.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + list_hosts_response = list_hosts( - self.apiclient, - id=vms[0].hostid - ) + self.apiclient, + id=vms[0].hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_disabled.hostid) cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() cmd.id = vm_with_ha_disabled.hostid diff --git a/test/integration/component/test_vpc_host_maintenance.py b/test/integration/component/test_vpc_host_maintenance.py index 1cce2764fe8..d28b7985b9b 100644 --- a/test/integration/component/test_vpc_host_maintenance.py +++ b/test/integration/component/test_vpc_host_maintenance.py @@ -186,7 +186,6 @@ class Services: } -@unittest.skip("No suitable setup available for testing") class TestVMLifeCycleHostmaintenance(cloudstackTestCase): @classmethod @@ -562,7 +561,6 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): return -@unittest.skip("No suitable setup available for testing") class TestVPCNetworkRules(cloudstackTestCase): @classmethod From f854f5df87ee8c16ac231d2ae53dd7063ed970d5 Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Mon, 27 May 2013 14:50:55 +0900 Subject: [PATCH 154/201] fix debian packaging nfs-common is required for a basic NFS installation both in management server and agent. Signed-off-by: Hiroaki KAWAI --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index eec9ca25c7b..46dd50536b0 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Homepage: http://www.cloudstack.org/ Package: cloudstack-common Architecture: all -Depends: bash, genisoimage +Depends: bash, genisoimage, nfs-common Conflicts: cloud-scripts, cloud-utils, cloud-system-iso, cloud-console-proxy, cloud-daemonize, cloud-deps, cloud-python, cloud-setup Description: A common package which contains files which are shared by several CloudStack packages From 77c52f5ebb3c7d8c61be4a8ac0142a21d47e0535 Mon Sep 17 00:00:00 2001 From: radhikap Date: Mon, 27 May 2013 11:47:48 +0530 Subject: [PATCH 155/201] remove the 256 limit (multiple ip per nic- now unlimited) --- docs/en-US/multiple-ip-nic.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/en-US/multiple-ip-nic.xml b/docs/en-US/multiple-ip-nic.xml index 561ba0757b5..926235c3518 100644 --- a/docs/en-US/multiple-ip-nic.xml +++ b/docs/en-US/multiple-ip-nic.xml @@ -24,8 +24,7 @@ &PRODUCT; now provides you the ability to associate multiple private IP addresses per guest VM NIC. This feature is supported on all the network configurations—Basic, Advanced, and VPC. Security Groups, Static NAT and Port forwarding services are supported on these additional - IPs. In addition to the primary IP, you can assign additional IPs to the guest VM NIC. Up to 256 - IP addresses are allowed per NIC. + IPs. In addition to the primary IP, you can assign additional IPs to the guest VM NIC. As always, you can specify an IP from the guest subnet; if not specified, an IP is automatically picked up from the guest VM subnet. You can view the IPs associated with for each guest VM NICs on the UI. You can apply NAT on these additional guest IPs by using firewall From 8744d1cdf62a8642c2f1903162634e7093879cba Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Mon, 27 May 2013 15:52:23 +0900 Subject: [PATCH 156/201] CLOUDSTACK-2406: fix UI strings Japanese properties file was broken, fixed manually. We need to let the servlet container the encoding to use. Signed-off-by: Hiroaki KAWAI --- .../classes/resources/messages_ja.properties | 108 +++++++++--------- ui/index.jsp | 2 +- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/client/WEB-INF/classes/resources/messages_ja.properties b/client/WEB-INF/classes/resources/messages_ja.properties index e483a97804b..a6075958d6a 100644 --- a/client/WEB-INF/classes/resources/messages_ja.properties +++ b/client/WEB-INF/classes/resources/messages_ja.properties @@ -23,7 +23,7 @@ error.could.not.enable.zone=\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3067\u30 error.installWizard.message=\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u623b\u3063\u3066\u30a8\u30e9\u30fc\u3092\u4fee\u6b63\u3067\u304d\u307e\u3059\u3002 error.invalid.username.password=\u7121\u52b9\u306a\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9 error.login=\u30e6\u30fc\u30b6\u30fc\u540d/\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u8a18\u9332\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002 -error.menu.select=\u00e3\u0082\u00a2\u00e3\u0082\u00a4\u00e3\u0083\u0086\u00e3\u0083\u00a0\u00e3\u0081\u008c\u00e9\u0081\u00b8\u00e6\u008a\u009e\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00aa\u00e3\u0081\u0084\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0082\u00a2\u00e3\u0082\u00af\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e5\u00ae\u009f\u00e8\u00a1\u008c\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u0093\u00e3\u0081\u00a8\u00e3\u0081\u008c\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093 +error.menu.select=\u9805\u76ee\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u3044\u305f\u3081\u64cd\u4f5c\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002 error.mgmt.server.inaccessible=\u7ba1\u7406\u30b5\u30fc\u30d0\u30fc\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093\u3002\u5f8c\u3067\u518d\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 error.password.not.match=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093 error.please.specify.physical.network.tags=\u3053\u306e\u7269\u7406\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u30bf\u30b0\u3092\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002 @@ -32,11 +32,11 @@ error.something.went.wrong.please.correct.the.following=\u554f\u984c\u304c\u767a error.unable.to.reach.management.server=\u7ba1\u7406\u30b5\u30fc\u30d0\u30fc\u3068\u901a\u4fe1\u3067\u304d\u307e\u305b\u3093 error.unresolved.internet.name=\u3042\u306a\u305f\u306e\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u540d\u306f\u89e3\u6c7a\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 extractable=\u62bd\u51fa\u53ef\u80fd -force.delete.domain.warning=\u8b66\u544a\: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u3059\u3079\u3066\u306e\u5b50\u30c9\u30e1\u30a4\u30f3\u304a\u3088\u3073\u95a2\u9023\u3059\u308b\u3059\u3079\u3066\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3068\u305d\u306e\u30ea\u30bd\u30fc\u30b9\u304c\u524a\u9664\u3055\u308c\u307e\u3059\u3002 +force.delete.domain.warning=\u8b66\u544a: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u3059\u3079\u3066\u306e\u5b50\u30c9\u30e1\u30a4\u30f3\u304a\u3088\u3073\u95a2\u9023\u3059\u308b\u3059\u3079\u3066\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3068\u305d\u306e\u30ea\u30bd\u30fc\u30b9\u304c\u524a\u9664\u3055\u308c\u307e\u3059\u3002 force.delete=\u5f37\u5236\u524a\u9664 -force.remove.host.warning=\u8b66\u544a\: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u304c\u5f37\u5236\u7684\u306b\u505c\u6b62\u3055\u308c\u3001\u30af\u30e9\u30b9\u30bf\u30fc\u304b\u3089\u3053\u306e\u30db\u30b9\u30c8\u304c\u5f37\u5236\u7684\u306b\u89e3\u9664\u3055\u308c\u307e\u3059\u3002 +force.remove.host.warning=\u8b66\u544a: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u304c\u5f37\u5236\u7684\u306b\u505c\u6b62\u3055\u308c\u3001\u30af\u30e9\u30b9\u30bf\u30fc\u304b\u3089\u3053\u306e\u30db\u30b9\u30c8\u304c\u5f37\u5236\u7684\u306b\u89e3\u9664\u3055\u308c\u307e\u3059\u3002 force.remove=\u5f37\u5236\u89e3\u9664 -force.stop.instance.warning=\u8b66\u544a\: \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u5f37\u5236\u505c\u6b62\u306f\u3001\u6700\u7d42\u624b\u6bb5\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30c7\u30fc\u30bf\u3092\u640d\u5931\u3059\u308b\u3060\u3051\u3067\u306a\u304f\u3001\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u52d5\u4f5c\u304c\u4e00\u8cab\u3057\u306a\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +force.stop.instance.warning=\u8b66\u544a: \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u5f37\u5236\u505c\u6b62\u306f\u3001\u6700\u7d42\u624b\u6bb5\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30c7\u30fc\u30bf\u3092\u640d\u5931\u3059\u308b\u3060\u3051\u3067\u306a\u304f\u3001\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u52d5\u4f5c\u304c\u4e00\u8cab\u3057\u306a\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 force.stop=\u5f37\u5236\u505c\u6b62 ICMP.code=ICMP \u30b3\u30fc\u30c9 ICMP.type=ICMP \u306e\u7a2e\u985e @@ -230,7 +230,7 @@ label.action.update.resource.count.processing=\u30ea\u30bd\u30fc\u30b9\u6570\u30 label.action.update.resource.count=\u30ea\u30bd\u30fc\u30b9\u6570\u306e\u66f4\u65b0 label.activate.project=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30a2\u30af\u30c6\u30a3\u30d6\u5316 label.active.sessions=\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u30bb\u30c3\u30b7\u30e7\u30f3 -label.add.accounts.to=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0\u5148\: +label.add.accounts.to=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0\u5148: label.add.accounts=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0 label.add.account.to.project=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3078\u306e\u8ffd\u52a0 label.add.account=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0 @@ -456,7 +456,7 @@ label.domain.admin=\u30c9\u30e1\u30a4\u30f3\u7ba1\u7406\u8005 label.domain.id=\u30c9\u30e1\u30a4\u30f3 ID label.domain.name=\u30c9\u30e1\u30a4\u30f3\u540d label.domain.router=\u30c9\u30e1\u30a4\u30f3 \u30eb\u30fc\u30bf\u30fc -label.domain.suffix=DNS \u30c9\u30e1\u30a4\u30f3 \u30b5\u30d5\u30a3\u30c3\u30af\u30b9 (\u4f8b\: xyz.com) +label.domain.suffix=DNS \u30c9\u30e1\u30a4\u30f3 \u30b5\u30d5\u30a3\u30c3\u30af\u30b9 (\u4f8b: xyz.com) label.domain=\u30c9\u30e1\u30a4\u30f3 label.done=\u5b8c\u4e86 label.double.quotes.are.not.allowed=\u4e8c\u91cd\u5f15\u7528\u7b26\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093 @@ -534,7 +534,7 @@ label.host.alerts=\u30db\u30b9\u30c8 \u30a2\u30e9\u30fc\u30c8 label.host.MAC=\u30db\u30b9\u30c8\u306e MAC label.host.name=\u30db\u30b9\u30c8\u540d label.hosts=\u30db\u30b9\u30c8 -label.host.tags=\u00e3\u0083\u009b\u00e3\u0082\u00b9\u00e3\u0083\u0088\u00e3\u0082\u00bf\u00e3\u0082\u00b0 +label.host.tags=\u30db\u30b9\u30c8 \u30bf\u30b0 label.host=\u30db\u30b9\u30c8 label.hourly=\u6bce\u6642 label.hypervisor.capabilities=\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u306e\u6a5f\u80fd @@ -563,8 +563,8 @@ label.installWizard.addZoneIntro.subtitle=\u30be\u30fc\u30f3\u306b\u3064\u3044\u label.installWizard.addZoneIntro.title=\u30be\u30fc\u30f3\u3092\u8ffd\u52a0\u3057\u307e\u3057\u3087\u3046 label.installWizard.addZone.title=\u30be\u30fc\u30f3\u306e\u8ffd\u52a0 label.installWizard.click.launch=[\u8d77\u52d5] \u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -label.installWizard.subtitle=\u3053\u306e\u30ac\u30a4\u30c9 \u30c4\u30a2\u30fc\u306f CloudStack&\#8482; \u74b0\u5883\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u306b\u5f79\u7acb\u3061\u307e\u3059 -label.installWizard.title=CloudStack&\#8482; \u3078\u3088\u3046\u3053\u305d +label.installWizard.subtitle=\u3053\u306e\u30ac\u30a4\u30c9 \u30c4\u30a2\u30fc\u306f CloudStack™ \u74b0\u5883\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u306b\u5f79\u7acb\u3061\u307e\u3059 +label.installWizard.title=CloudStack™ \u3078\u3088\u3046\u3053\u305d label.instance.limits=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5236\u9650 label.instance.name=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u540d label.instances=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9 @@ -573,12 +573,12 @@ label.internal.dns.1=\u5185\u90e8 DNS 1 label.internal.dns.2=\u5185\u90e8 DNS 2 label.internal.name=\u5185\u90e8\u540d label.interval.type=\u9593\u9694\u306e\u7a2e\u985e -label.introduction.to.cloudstack=CloudStack&\#8482; \u306e\u7d39\u4ecb +label.introduction.to.cloudstack=CloudStack™ \u306e\u7d39\u4ecb label.invalid.integer=\u7121\u52b9\u306a\u6574\u6570 label.invalid.number=\u7121\u52b9\u306a\u6570 label.invitations=\u62db\u5f85\u72b6 label.invited.accounts=\u62db\u5f85\u6e08\u307f\u30a2\u30ab\u30a6\u30f3\u30c8 -label.invite.to=\u62db\u5f85\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\: +label.invite.to=\u62db\u5f85\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8: label.invite=\u62db\u5f85 label.ip.address=IP \u30a2\u30c9\u30ec\u30b9 label.ipaddress=IP \u30a2\u30c9\u30ec\u30b9 @@ -695,9 +695,9 @@ label.menu.virtual.resources=\u4eee\u60f3\u30ea\u30bd\u30fc\u30b9 label.menu.volumes=\u30dc\u30ea\u30e5\u30fc\u30e0 label.migrate.instance.to.host=\u5225\u306e\u30db\u30b9\u30c8\u3078\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c label.migrate.instance.to.ps=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3078\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c -label.migrate.instance.to=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c\u5148\: -label.migrate.router.to=\u30eb\u30fc\u30bf\u30fc\u306e\u79fb\u884c\u5148\: -label.migrate.systemvm.to=\u30b7\u30b9\u30c6\u30e0 VM \u306e\u79fb\u884c\u5148\: +label.migrate.instance.to=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c\u5148: +label.migrate.router.to=\u30eb\u30fc\u30bf\u30fc\u306e\u79fb\u884c\u5148: +label.migrate.systemvm.to=\u30b7\u30b9\u30c6\u30e0 VM \u306e\u79fb\u884c\u5148: label.migrate.to.host=\u30db\u30b9\u30c8\u3078\u79fb\u884c label.migrate.to.storage=\u30b9\u30c8\u30ec\u30fc\u30b8\u3078\u79fb\u884c label.migrate.volume=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3078\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u79fb\u884c @@ -785,7 +785,7 @@ label.os.preference=OS \u57fa\u672c\u8a2d\u5b9a label.os.type=OS \u306e\u7a2e\u985e label.owned.public.ips=\u6240\u6709\u3059\u308b\u30d1\u30d6\u30ea\u30c3\u30af IP \u30a2\u30c9\u30ec\u30b9 label.owner.account=\u6240\u6709\u8005\u30a2\u30ab\u30a6\u30f3\u30c8 -label.owner.domain=\u00e6\u0089\u0080\u00e6\u009c\u0089\u00e8\u0080 +label.owner.domain=\u6240\u6709\u8005\u30c9\u30e1\u30a4\u30f3 label.parent.domain=\u89aa\u30c9\u30e1\u30a4\u30f3 label.password.enabled=\u30d1\u30b9\u30ef\u30fc\u30c9\u7ba1\u7406\u6709\u52b9 label.password=\u30d1\u30b9\u30ef\u30fc\u30c9 @@ -817,7 +817,7 @@ label.private.interface=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30a4\u30f3\u30bf\ label.private.ip.range=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2 label.private.ips=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 IP \u30a2\u30c9\u30ec\u30b9 label.private.ip=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 IP \u30a2\u30c9\u30ec\u30b9 -label.privatekey=PKC\#8 \u79d8\u5bc6\u30ad\u30fc +label.privatekey=PKC#8 \u79d8\u5bc6\u30ad\u30fc label.private.network=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af label.private.port=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30dd\u30fc\u30c8 label.private.zone=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30be\u30fc\u30f3 @@ -951,7 +951,7 @@ label.start.reserved.system.IP=\u4e88\u7d04\u6e08\u307f\u958b\u59cb\u30b7\u30b9\ label.start.vlan=\u958b\u59cb VLAN label.state=\u72b6\u614b label.static.nat.enabled=\u9759\u7684 NAT \u6709\u52b9 -label.static.nat.to=\u9759\u7684 NAT \u306e\u8a2d\u5b9a\u5148\: +label.static.nat.to=\u9759\u7684 NAT \u306e\u8a2d\u5b9a\u5148: label.static.nat=\u9759\u7684 NAT label.static.nat.vm.details=\u9759\u7684 NAT VM \u306e\u8a73\u7d30 label.statistics=\u7d71\u8a08 @@ -960,7 +960,7 @@ label.step.1.title=\u624b\u9806 1. \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\ label.step.1=\u624b\u9806 1 label.step.2.title=\u624b\u9806 2. \u30b5\u30fc\u30d3\u30b9 \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0 label.step.2=\u624b\u9806 2 -label.step.3.title=\u624b\u9806 3. \u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u306e\u9078\u629e +label.step.3.title=\u624b\u9806 3. \u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u306e\u9078\u629e label.step.3=\u624b\u9806 3 label.step.4.title=\u624b\u9806 4. \u30cd\u30c3\u30c8\u30ef\u30fc\u30af label.step.4=\u624b\u9806 4 @@ -986,7 +986,7 @@ label.storage.traffic=\u30b9\u30c8\u30ec\u30fc\u30b8 \u30c8\u30e9\u30d5\u30a3\u3 label.storage.type=\u30b9\u30c8\u30ec\u30fc\u30b8\u306e\u7a2e\u985e label.storage=\u30b9\u30c8\u30ec\u30fc\u30b8 label.subdomain.access=\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3 \u30a2\u30af\u30bb\u30b9 -label.submitted.by=[\u9001\u4fe1\u30e6\u30fc\u30b6\u30fc\: ] +label.submitted.by=[\u9001\u4fe1\u30e6\u30fc\u30b6\u30fc: ] label.submit=\u9001\u4fe1 label.succeeded=\u6210\u529f label.sunday=\u65e5\u66dc\u65e5 @@ -1061,7 +1061,7 @@ label.vcipaddress=vCenter IP \u30a2\u30c9\u30ec\u30b9 label.version=\u30d0\u30fc\u30b8\u30e7\u30f3 label.view.all=\u3059\u3079\u3066\u8868\u793a label.view.console=\u30b3\u30f3\u30bd\u30fc\u30eb\u306e\u8868\u793a -label.viewing=\u8868\u793a\u9805\u76ee\: +label.viewing=\u8868\u793a\u9805\u76ee: label.view.more=\u8a73\u7d30\u8868\u793a label.view=\u8868\u793a - label.virtual.appliances=\u4eee\u60f3\u30a2\u30d7\u30e9\u30a4\u30a2\u30f3\u30b9 @@ -1110,7 +1110,7 @@ label.wednesday=\u6c34\u66dc\u65e5 label.weekly=\u6bce\u9031 label.welcome.cloud.console=\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30eb\u3078\u3088\u3046\u3053\u305d label.welcome=\u3088\u3046\u3053\u305d -label.what.is.cloudstack=CloudStack&\#8482; \u306b\u3064\u3044\u3066 +label.what.is.cloudstack=CloudStack™ \u306b\u3064\u3044\u3066 label.xen.traffic.label=XenServer \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306e\u30e9\u30d9\u30eb label.yes=\u306f\u3044 label.zone.details=\u30be\u30fc\u30f3\u306e\u8a73\u7d30 @@ -1124,9 +1124,9 @@ label.zones=\u30be\u30fc\u30f3 label.zone.type=\u30be\u30fc\u30f3\u306e\u7a2e\u985e label.zone=\u30be\u30fc\u30f3 label.zone.wide=\u30be\u30fc\u30f3\u5168\u4f53 -label.zoneWizard.trafficType.guest=\u30b2\u30b9\u30c8\: \u30a8\u30f3\u30c9\u30e6\u30fc\u30b6\u30fc\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af -label.zoneWizard.trafficType.public=\u30d1\u30d6\u30ea\u30c3\u30af\: \u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u3068\u30af\u30e9\u30a6\u30c9\u5185\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af -label.zoneWizard.trafficType.storage=\u30b9\u30c8\u30ec\u30fc\u30b8\: VM\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3068\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u306e\u3088\u3046\u306a\u3001\u30d7\u30e9\u30a4\u30de\u30ea\u3068\u30bb\u30ab\u30f3\u30c0\u30ea\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u30b5\u30fc\u30d0\u30fc\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u3002 +label.zoneWizard.trafficType.guest=\u30b2\u30b9\u30c8: \u30a8\u30f3\u30c9\u30e6\u30fc\u30b6\u30fc\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af +label.zoneWizard.trafficType.public=\u30d1\u30d6\u30ea\u30c3\u30af: \u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u3068\u30af\u30e9\u30a6\u30c9\u5185\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af +label.zoneWizard.trafficType.storage=\u30b9\u30c8\u30ec\u30fc\u30b8: VM\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3068\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u306e\u3088\u3046\u306a\u3001\u30d7\u30e9\u30a4\u30de\u30ea\u3068\u30bb\u30ab\u30f3\u30c0\u30ea\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u30b5\u30fc\u30d0\u30fc\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u3002 managed.state=\u7ba1\u7406\u5bfe\u8c61\u72b6\u614b message.acquire.new.ip=\u3053\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u65b0\u3057\u3044 IP \u30a2\u30c9\u30ec\u30b9\u3092\u53d6\u5f97\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.acquire.new.ip.vpc=VPC\u306e\u65b0\u3057\u3044IP\u3092\u53d6\u5f97\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 @@ -1138,8 +1138,8 @@ message.action.change.service.warning.for.router=\u73fe\u5728\u306e\u30b5\u30fc\ message.action.delete.cluster=\u3053\u306e\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.disk.offering=\u3053\u306e\u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.domain=\u3053\u306e\u30c9\u30e1\u30a4\u30f3\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.action.delete.external.firewall=\u3053\u306e\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a\: \u540c\u3058\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -message.action.delete.external.load.balancer=\u3053\u306e\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a\: \u540c\u3058\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +message.action.delete.external.firewall=\u3053\u306e\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a: \u540c\u3058\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +message.action.delete.external.load.balancer=\u3053\u306e\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a: \u540c\u3058\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 message.action.delete.ingress.rule=\u3053\u306e\u53d7\u4fe1\u898f\u5247\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.ISO.for.all.zones=\u305d\u306e ISO \u306f\u3059\u3079\u3066\u306e\u30be\u30fc\u30f3\u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u3059\u3079\u3066\u306e\u30be\u30fc\u30f3\u304b\u3089\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.ISO=\u3053\u306e ISO \u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? @@ -1175,9 +1175,9 @@ message.action.enable.pod=\u3053\u306e\u30dd\u30c3\u30c9\u3092\u6709\u52b9\u306b message.action.enable.zone=\u3053\u306e\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.force.reconnect=\u30db\u30b9\u30c8\u306f\u5f37\u5236\u7684\u306b\u518d\u63a5\u7d9a\u3057\u307e\u3057\u305f\u3002\u3053\u306e\u51e6\u7406\u306b\u306f\u6570\u5206\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 message.action.host.enable.maintenance.mode=\u4fdd\u5b88\u30e2\u30fc\u30c9\u3092\u6709\u52b9\u306b\u3059\u308b\u3068\u3001\u3053\u306e\u30db\u30b9\u30c8\u3067\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u307b\u304b\u306e\u4f7f\u7528\u3067\u304d\u308b\u30db\u30b9\u30c8\u306b\u30e9\u30a4\u30d6 \u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3055\u308c\u307e\u3059\u3002 -message.action.instance.reset.password=\u00e3\u0081\u0093\u00e3\u0081\u00ae\u00e4\u00bb\u00ae\u00e6\u0083\u00b3\u00e3\u0083\u009e\u00e3\u0082\u00b7\u00e3\u0083\u00b3\u00e3\u0081\u00ae\u00e3\u0083\u00ab\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0083\u0091\u00e3\u0082\u00b9\u00e3\u0083\u00af\u00e3\u0083\u00bc\u00e3\u0083\u0089\u00e3\u0082\u0092\u00e5\u00a4\u0089\u00e6\u009b\u00b4\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0082\u0082\u00e3\u0082\u0088\u00e3\u0082\u008d\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0081\u008b? +message.action.instance.reset.password=\u3053\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u30eb\u30fc\u30c8 \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5909\u66f4\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.manage.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u7ba1\u7406\u5bfe\u8c61\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.action.primarystorage.enable.maintenance.mode=\u8b66\u544a\: \u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4fdd\u5b88\u30e2\u30fc\u30c9\u306b\u3059\u308b\u3068\u3001\u305d\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u4e0a\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u4f7f\u7528\u3059\u308b\u3059\u3079\u3066\u306e VM \u304c\u505c\u6b62\u3057\u307e\u3059\u3002\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? +message.action.primarystorage.enable.maintenance.mode=\u8b66\u544a: \u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4fdd\u5b88\u30e2\u30fc\u30c9\u306b\u3059\u308b\u3068\u3001\u305d\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u4e0a\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u4f7f\u7528\u3059\u308b\u3059\u3079\u3066\u306e VM \u304c\u505c\u6b62\u3057\u307e\u3059\u3002\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.reboot.instance=\u3053\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.reboot.router=\u3053\u306e\u4eee\u60f3\u30eb\u30fc\u30bf\u30fc\u3067\u63d0\u4f9b\u3059\u308b\u3059\u3079\u3066\u306e\u30b5\u30fc\u30d3\u30b9\u304c\u4e2d\u65ad\u3055\u308c\u307e\u3059\u3002\u3053\u306e\u30eb\u30fc\u30bf\u30fc\u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.reboot.systemvm=\u3053\u306e\u30b7\u30b9\u30c6\u30e0 VM \u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? @@ -1195,8 +1195,8 @@ message.action.stop.systemvm=\u3053\u306e\u30b7\u30b9\u30c6\u30e0 VM \u3092\u505 message.action.take.snapshot=\u3053\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u3092\u4f5c\u6210\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.unmanage.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u975e\u7ba1\u7406\u5bfe\u8c61\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.activate.project=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u30a2\u30af\u30c6\u30a3\u30d6\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.add.cluster=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.cluster.zone=\u30be\u30fc\u30f3 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.cluster=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.cluster.zone=\u30be\u30fc\u30f3 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.disk.offering=\u65b0\u3057\u3044\u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.domain=\u3053\u306e\u30c9\u30e1\u30a4\u30f3\u306b\u4f5c\u6210\u3059\u308b\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.firewall=\u30be\u30fc\u30f3\u306b\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u8ffd\u52a0\u3057\u307e\u3059 @@ -1205,18 +1205,18 @@ message.add.host=\u65b0\u3057\u3044\u30db\u30b9\u30c8\u3092\u8ffd\u52a0\u3059\u3 message.adding.host=\u30db\u30b9\u30c8\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059 message.adding.Netscaler.device=Netscaler \u30c7\u30d0\u30a4\u30b9\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059 message.adding.Netscaler.provider=Netscaler \u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059 -message.add.ip.range.direct.network=\u30be\u30fc\u30f3 \u306e\u76f4\u63a5\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.ip.range.to.pod=

    \u30dd\u30c3\u30c9 \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059

    +message.add.ip.range.direct.network=\u30be\u30fc\u30f3 \u306e\u76f4\u63a5\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.ip.range.to.pod=

    \u30dd\u30c3\u30c9 \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059

    message.add.ip.range=\u30be\u30fc\u30f3\u306e\u30d1\u30d6\u30ea\u30c3\u30af \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.additional.networks.desc=\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u63a5\u7d9a\u3059\u308b\u8ffd\u52a0\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.load.balancer=\u30be\u30fc\u30f3\u306b\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.load.balancer.under.ip=\u8ca0\u8377\u5206\u6563\u898f\u5247\u304c\u6b21\u306e IP \u30a2\u30c9\u30ec\u30b9\u306b\u5bfe\u3057\u3066\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\: -message.add.network=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.load.balancer.under.ip=\u8ca0\u8377\u5206\u6563\u898f\u5247\u304c\u6b21\u306e IP \u30a2\u30c9\u30ec\u30b9\u306b\u5bfe\u3057\u3066\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f: +message.add.network=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.new.gateway.to.vpc=\u3053\u306e VPC \u306b\u65b0\u3057\u3044\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.pod=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30dd\u30c3\u30c9\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.primary.storage=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u65b0\u3057\u3044\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.pod=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30dd\u30c3\u30c9\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.primary.storage=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u65b0\u3057\u3044\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.primary=\u65b0\u3057\u3044\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.secondary.storage=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.secondary.storage=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.service.offering=\u65b0\u3057\u3044\u30b3\u30f3\u30d4\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0 \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.system.service.offering=\u65b0\u3057\u3044\u30b7\u30b9\u30c6\u30e0 \u30b5\u30fc\u30d3\u30b9 \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.template=\u65b0\u3057\u3044\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 @@ -1225,8 +1225,8 @@ message.add.VPN.gateway=VPN \u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u3092\u8ffd\u52 message.advanced.mode.desc=VLAN \u30b5\u30dd\u30fc\u30c8\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408\u306f\u3001\u3053\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30e2\u30c7\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u30e2\u30c7\u30eb\u3067\u306f\u6700\u3082\u67d4\u8edf\u306b\u30ab\u30b9\u30bf\u30e0 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u63d0\u4f9b\u3067\u304d\u3001\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3001VPN\u3001\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u306e\u30b5\u30dd\u30fc\u30c8\u306e\u307b\u304b\u306b\u3001\u76f4\u63a5\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3068\u4eee\u60f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3082\u6709\u52b9\u306b\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 message.advanced.security.group=\u30b2\u30b9\u30c8 VM \u3092\u5206\u96e2\u3059\u308b\u305f\u3081\u306b\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3 \u30b0\u30eb\u30fc\u30d7\u3092\u4f7f\u7528\u3059\u308b\u5834\u5408\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.advanced.virtual=\u30b2\u30b9\u30c8 VM \u3092\u5206\u96e2\u3059\u308b\u305f\u3081\u306b\u30be\u30fc\u30f3\u5168\u4f53\u306e VLAN \u3092\u4f7f\u7528\u3059\u308b\u5834\u5408\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.after.enable.s3=S3\u57fa\u76e4\u30bb\u30ab\u30f3\u30c0\u30ea\u30b9\u30c8\u30ec\u30fc\u30b8\u304c\u8a2d\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002 \u30ce\u30fc\u30c8\:\u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068S3\u3092\u518d\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002 -message.after.enable.swift=Swift \u304c\u69cb\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u6ce8\: \u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068\u3001Swift \u3092\u518d\u69cb\u6210\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +message.after.enable.s3=S3\u57fa\u76e4\u30bb\u30ab\u30f3\u30c0\u30ea\u30b9\u30c8\u30ec\u30fc\u30b8\u304c\u8a2d\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002 \u30ce\u30fc\u30c8:\u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068S3\u3092\u518d\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002 +message.after.enable.swift=Swift \u304c\u69cb\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u6ce8: \u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068\u3001Swift \u3092\u518d\u69cb\u6210\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 message.alert.state.detected=\u30a2\u30e9\u30fc\u30c8\u72b6\u614b\u304c\u691c\u51fa\u3055\u308c\u307e\u3057\u305f message.allow.vpn.access=VPN \u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3059\u308b\u30e6\u30fc\u30b6\u30fc\u306e\u30e6\u30fc\u30b6\u30fc\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.apply.snapshot.policy=\u73fe\u5728\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 \u30dd\u30ea\u30b7\u30fc\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002 @@ -1251,10 +1251,10 @@ message.confirm.join.project=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3 message.confirm.remove.IP.range=\u3053\u306e IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.confirm.shutdown.provider=\u3053\u306e\u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u3092\u30b7\u30e3\u30c3\u30c8\u30c0\u30a6\u30f3\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.copy.iso.confirm=ISO \u3092\u6b21\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.copy.template=\u30be\u30fc\u30f3 \u304b\u3089\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 XXX \u3092\u6b21\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059\: +message.copy.template=\u30be\u30fc\u30f3 \u304b\u3089\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 XXX \u3092\u6b21\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059: message.create.template=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.create.template.vm=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 \u304b\u3089 VM \u3092\u4f5c\u6210\u3057\u307e\u3059 -message.create.template.volume=\u30c7\u30a3\u30b9\u30af \u30dc\u30ea\u30e5\u30fc\u30e0 \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u524d\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30dc\u30ea\u30e5\u30fc\u30e0 \u30b5\u30a4\u30ba\u306b\u3088\u3063\u3066\u306f\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u306f\u6570\u5206\u4ee5\u4e0a\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +message.create.template.vm=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 \u304b\u3089 VM \u3092\u4f5c\u6210\u3057\u307e\u3059 +message.create.template.volume=\u30c7\u30a3\u30b9\u30af \u30dc\u30ea\u30e5\u30fc\u30e0 \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u524d\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30dc\u30ea\u30e5\u30fc\u30e0 \u30b5\u30a4\u30ba\u306b\u3088\u3063\u3066\u306f\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u306f\u6570\u5206\u4ee5\u4e0a\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 message.creating.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059 message.creating.guest.network=\u30b2\u30b9\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059 message.creating.physical.networks=\u7269\u7406\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059 @@ -1278,21 +1278,21 @@ message.desc.secondary.storage=\u5404\u30be\u30fc\u30f3\u306b\u306f\u5c11\u306a\ message.desc.zone=\u30be\u30fc\u30f3\u306f CloudStack \u74b0\u5883\u5185\u306e\u6700\u5927\u306e\u7d44\u7e54\u5358\u4f4d\u3067\u3001\u901a\u5e38\u3001\u5358\u4e00\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u306b\u76f8\u5f53\u3057\u307e\u3059\u3002\u30be\u30fc\u30f3\u306b\u3088\u3063\u3066\u7269\u7406\u7684\u306a\u5206\u96e2\u3068\u5197\u9577\u6027\u304c\u63d0\u4f9b\u3055\u308c\u307e\u3059\u3002\u30be\u30fc\u30f3\u306f 1 \u3064\u4ee5\u4e0a\u306e\u30dd\u30c3\u30c9 (\u5404\u30dd\u30c3\u30c9\u306f\u30db\u30b9\u30c8\u3068\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8 \u30b5\u30fc\u30d0\u30fc\u304b\u3089\u69cb\u6210\u3055\u308c\u307e\u3059) \u3068\u3001\u30be\u30fc\u30f3\u5185\u306e\u3059\u3079\u3066\u306e\u30dd\u30c3\u30c9\u3067\u5171\u6709\u3055\u308c\u308b\u30bb\u30ab\u30f3\u30c0\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8 \u30b5\u30fc\u30d0\u30fc\u304b\u3089\u69cb\u6210\u3055\u308c\u307e\u3059\u3002 message.detach.disk=\u3053\u306e\u30c7\u30a3\u30b9\u30af\u3092\u30c7\u30bf\u30c3\u30c1\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.detach.iso.confirm=\u3053\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304b\u3089 ISO \u30d5\u30a1\u30a4\u30eb\u3092\u30c7\u30bf\u30c3\u30c1\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.disable.account=\u00e3\u0081\u0093\u00e3\u0081\u00ae\u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u0084\u00a1\u00e5\u008a\u00b9\u00e3\u0081\u00ab\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0082\u0082\u00e3\u0082\u0088\u00e3\u0082\u008d\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0081\u008b? \u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u0084\u00a1\u00e5\u008a\u00b9\u00e3\u0081\u00ab\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u0093\u00e3\u0081\u00a8\u00e3\u0081\u00ab\u00e3\u0082\u0088\u00e3\u0082\u008a\u00e3\u0080\u0081\u00e3\u0081\u0093\u00e3\u0081\u00ae\u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e3\u0081\u0099\u00e3\u0081\u00b9\u00e3\u0081\u00a6\u00e3\u0081\u00ae\u00e3\u0083\u00a6\u00e3\u0083\u00bc\u00e3\u0082\u00b6\u00e3\u0083\u00bc\u00e3\u0081\u00af\u00e3\u0082\u00af\u00e3\u0083\u00a9\u00e3\u0082\u00a6\u00e3\u0083\u0089\u00e3\u0083\u00aa\u00e3\u0082\u00bd\u00e3\u0083\u00bc\u00e3\u0082\u00b9\u00e3\u0081\u00ab\u00e3\u0082\u00a2\u00e3\u0082\u00af\u00e3\u0082\u00bb\u00e3\u0082\u00b9\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00aa\u00e3\u0081\u008f\u00e3\u0081\u00aa\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e5\u00ae\u009f\u00e8\u00a1\u008c\u00e4\u00b8\u00ad\u00e3\u0081\u00ae\u00e3\u0081\u0099\u00e3\u0081\u00b9\u00e3\u0081\u00a6\u00e3\u0081\u00ae\u00e4\u00bb\u00ae\u00e6\u0083\u00b3\u00e3\u0083\u009e\u00e3\u0082\u00b7\u00e3\u0083\u00b3\u00e3\u0081\u00af\u00e3\u0081\u0099\u00e3\u0081\u0090\u00e3\u0081\u00ab\u00e3\u0082\u00b7\u00e3\u0083\u00a3\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0083\u0080\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +message.disable.account=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u3059\u3079\u3066\u306e\u30e6\u30fc\u30b6\u30fc\u304c\u30af\u30e9\u30a6\u30c9 \u30ea\u30bd\u30fc\u30b9\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306f\u4eca\u3059\u3050\u306b\u30b7\u30e3\u30c3\u30c8\u30c0\u30a6\u30f3\u3055\u308c\u307e\u3059\u3002 message.disable.snapshot.policy=\u73fe\u5728\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 \u30dd\u30ea\u30b7\u30fc\u3092\u7121\u52b9\u306b\u3057\u307e\u3057\u305f\u3002 message.disable.user=\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.disable.vpn.access=VPN \u30a2\u30af\u30bb\u30b9\u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.disable.vpn=VPN \u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.download.ISO=ISO\u00e3\u0082\u0092\u00e3\u0083\u0080\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u00ad\u00e3\u0083\u00bc\u00e3\u0083\u0089\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab00000\u00e3\u0082\u0092\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0083\u00e3\u0082\u00af\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u008f\u00e3\u0081\u00a0\u00e3\u0081\u0095\u00e3\u0081\u0084\u00e3\u0080\u0082 -message.download.template=\u00e3\u0083\u0086\u00e3\u0083\u00b3\u00e3\u0083\u0097\u00e3\u0083\u00ac\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e3\u0083\u0080\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u00ad\u00e3\u0083\u00bc\u00e3\u0083\u0089\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab00000\u00e3\u0082\u0092\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0083\u00e3\u0082\u00af\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u008f\u00e3\u0081\u00a0\u00e3\u0081\u0095\u00e3\u0081\u0084\u00e3\u0080\u0082 +message.download.ISO=ISO \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 +message.download.template=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 message.download.volume.confirm=\u3053\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.download.volume=\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 +message.download.volume=\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 message.edit.account=\u7de8\u96c6 ("-1" \u306f\u3001\u30ea\u30bd\u30fc\u30b9\u4f5c\u6210\u306e\u91cf\u306b\u5236\u9650\u304c\u306a\u3044\u3053\u3068\u3092\u793a\u3057\u307e\u3059) message.edit.confirm=[\u4fdd\u5b58] \u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u524d\u306b\u5909\u66f4\u5185\u5bb9\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.edit.limits=\u6b21\u306e\u30ea\u30bd\u30fc\u30b9\u306b\u5236\u9650\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u300c-1\u300d\u306f\u3001\u30ea\u30bd\u30fc\u30b9\u4f5c\u6210\u306b\u5236\u9650\u304c\u306a\u3044\u3053\u3068\u3092\u793a\u3057\u307e\u3059\u3002 message.edit.traffic.type=\u3053\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306e\u7a2e\u985e\u306b\u95a2\u9023\u4ed8\u3051\u308b\u30c8\u30e9\u30d5\u30a3\u30c3\u30af \u30e9\u30d9\u30eb\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.enable.account=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.enabled.vpn.ip.sec=IPSec \u4e8b\u524d\u5171\u6709\u30ad\u30fc\: +message.enabled.vpn.ip.sec=IPSec \u4e8b\u524d\u5171\u6709\u30ad\u30fc: message.enabled.vpn=\u73fe\u5728\u3001VPN \u30a2\u30af\u30bb\u30b9\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002\u6b21\u306e IP \u30a2\u30c9\u30ec\u30b9\u7d4c\u7531\u3067\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002 message.enable.user=\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.enable.vpn.access=\u73fe\u5728\u3053\u306e IP \u30a2\u30c9\u30ec\u30b9\u306b\u5bfe\u3059\u308b VPN \u306f\u7121\u52b9\u3067\u3059\u3002VPN \u30a2\u30af\u30bb\u30b9\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? @@ -1304,8 +1304,8 @@ message.generate.keys=\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u306b\u65b0\u3057\u30 message.guest.traffic.in.advanced.zone=\u30b2\u30b9\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306f\u3001\u30a8\u30f3\u30c9 \u30e6\u30fc\u30b6\u30fc\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u901a\u4fe1\u3067\u3059\u3002\u5404\u7269\u7406\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u30b2\u30b9\u30c8 \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u3092\u901a\u4fe1\u3059\u308b\u305f\u3081\u306e VLAN ID \u306e\u7bc4\u56f2\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.guest.traffic.in.basic.zone=\u30b2\u30b9\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306f\u3001\u30a8\u30f3\u30c9 \u30e6\u30fc\u30b6\u30fc\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u901a\u4fe1\u3067\u3059\u3002CloudStack \u3067\u30b2\u30b9\u30c8 VM \u306b\u5272\u308a\u5f53\u3066\u3089\u308c\u308b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u7bc4\u56f2\u304c\u4e88\u7d04\u6e08\u307f\u306e\u30b7\u30b9\u30c6\u30e0 IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3068\u91cd\u8907\u3057\u306a\u3044\u3088\u3046\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.installWizard.click.retry=\u8d77\u52d5\u3092\u518d\u8a66\u884c\u3059\u308b\u306b\u306f\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.installWizard.copy.whatIsAPod=\u901a\u5e38\u30011 \u3064\u306e\u30dd\u30c3\u30c9\u306f\u5358\u4e00\u306e\u30e9\u30c3\u30af\u3092\u8868\u3057\u307e\u3059\u3002\u540c\u3058\u30dd\u30c3\u30c9\u5185\u306e\u30db\u30b9\u30c8\u306f\u540c\u3058\u30b5\u30d6\u30cd\u30c3\u30c8\u306b\u542b\u307e\u308c\u307e\u3059\u3002

    \u30dd\u30c3\u30c9\u306f CloudStack&\#8482; \u74b0\u5883\u5185\u306e 2 \u756a\u76ee\u306b\u5927\u304d\u306a\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u3002\u30dd\u30c3\u30c9\u306f\u30be\u30fc\u30f3\u306b\u542b\u307e\u308c\u307e\u3059\u3002\u5404\u30be\u30fc\u30f3\u306f 1 \u3064\u4ee5\u4e0a\u306e\u30dd\u30c3\u30c9\u3092\u542b\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u57fa\u672c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u306f\u3001\u30be\u30fc\u30f3\u5185\u306e\u30dd\u30c3\u30c9\u306f 1 \u3064\u3067\u3059\u3002 -message.installWizard.copy.whatIsAZone=\u30be\u30fc\u30f3\u306f CloudStack&\#8482; \u74b0\u5883\u5185\u306e\u6700\u5927\u306e\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u30021 \u3064\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u5185\u306b\u8907\u6570\u306e\u30be\u30fc\u30f3\u3092\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u304c\u3001\u901a\u5e38\u3001\u30be\u30fc\u30f3\u306f\u5358\u4e00\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u306b\u76f8\u5f53\u3057\u307e\u3059\u3002\u30a4\u30f3\u30d5\u30e9\u30b9\u30c8\u30e9\u30af\u30c1\u30e3\u3092\u30be\u30fc\u30f3\u306b\u7d44\u7e54\u5316\u3059\u308b\u3068\u3001\u30be\u30fc\u30f3\u3092\u7269\u7406\u7684\u306b\u5206\u96e2\u3057\u3066\u5197\u9577\u5316\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u305f\u3068\u3048\u3070\u3001\u5404\u30be\u30fc\u30f3\u306b\u96fb\u6e90\u3068\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30a2\u30c3\u30d7\u30ea\u30f3\u30af\u3092\u914d\u5099\u3057\u307e\u3059\u3002\u5fc5\u9808\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u30be\u30fc\u30f3\u306f\u9060\u9694\u5730\u306b\u5206\u6563\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 +message.installWizard.copy.whatIsAPod=\u901a\u5e38\u30011 \u3064\u306e\u30dd\u30c3\u30c9\u306f\u5358\u4e00\u306e\u30e9\u30c3\u30af\u3092\u8868\u3057\u307e\u3059\u3002\u540c\u3058\u30dd\u30c3\u30c9\u5185\u306e\u30db\u30b9\u30c8\u306f\u540c\u3058\u30b5\u30d6\u30cd\u30c3\u30c8\u306b\u542b\u307e\u308c\u307e\u3059\u3002

    \u30dd\u30c3\u30c9\u306f CloudStack™ \u74b0\u5883\u5185\u306e 2 \u756a\u76ee\u306b\u5927\u304d\u306a\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u3002\u30dd\u30c3\u30c9\u306f\u30be\u30fc\u30f3\u306b\u542b\u307e\u308c\u307e\u3059\u3002\u5404\u30be\u30fc\u30f3\u306f 1 \u3064\u4ee5\u4e0a\u306e\u30dd\u30c3\u30c9\u3092\u542b\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u57fa\u672c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u306f\u3001\u30be\u30fc\u30f3\u5185\u306e\u30dd\u30c3\u30c9\u306f 1 \u3064\u3067\u3059\u3002 +message.installWizard.copy.whatIsAZone=\u30be\u30fc\u30f3\u306f CloudStack™ \u74b0\u5883\u5185\u306e\u6700\u5927\u306e\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u30021 \u3064\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u5185\u306b\u8907\u6570\u306e\u30be\u30fc\u30f3\u3092\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u304c\u3001\u901a\u5e38\u3001\u30be\u30fc\u30f3\u306f\u5358\u4e00\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u306b\u76f8\u5f53\u3057\u307e\u3059\u3002\u30a4\u30f3\u30d5\u30e9\u30b9\u30c8\u30e9\u30af\u30c1\u30e3\u3092\u30be\u30fc\u30f3\u306b\u7d44\u7e54\u5316\u3059\u308b\u3068\u3001\u30be\u30fc\u30f3\u3092\u7269\u7406\u7684\u306b\u5206\u96e2\u3057\u3066\u5197\u9577\u5316\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u305f\u3068\u3048\u3070\u3001\u5404\u30be\u30fc\u30f3\u306b\u96fb\u6e90\u3068\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30a2\u30c3\u30d7\u30ea\u30f3\u30af\u3092\u914d\u5099\u3057\u307e\u3059\u3002\u5fc5\u9808\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u30be\u30fc\u30f3\u306f\u9060\u9694\u5730\u306b\u5206\u6563\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 message.installWizard.copy.whatIsSecondaryStorage=\u30bb\u30ab\u30f3\u30c0\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u306f\u30be\u30fc\u30f3\u3068\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3001\u6b21\u306e\u9805\u76ee\u3092\u683c\u7d0d\u3057\u307e\u3059\u3002
    • \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 - VM \u306e\u8d77\u52d5\u306b\u4f7f\u7528\u3067\u304d\u308b OS \u30a4\u30e1\u30fc\u30b8\u3067\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306a\u3069\u8ffd\u52a0\u306e\u69cb\u6210\u3092\u542b\u3081\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002
    • ISO \u30a4\u30e1\u30fc\u30b8 - \u8d77\u52d5\u53ef\u80fd\u307e\u305f\u306f\u8d77\u52d5\u4e0d\u53ef\u306e OS \u30a4\u30e1\u30fc\u30b8\u3067\u3059\u3002
    • \u30c7\u30a3\u30b9\u30af \u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 - VM \u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u30b3\u30d4\u30fc\u3067\u3059\u3002\u30c7\u30fc\u30bf\u306e\u5fa9\u5143\u307e\u305f\u306f\u65b0\u3057\u3044\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002
    message.installWizard.tooltip.addCluster.name=\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u540d\u524d\u3067\u3059\u3002CloudStack \u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u306a\u3044\u3001\u4efb\u610f\u306e\u30c6\u30ad\u30b9\u30c8\u3092\u6307\u5b9a\u3067\u304d\u307e\u3059\u3002 message.installWizard.tooltip.addHost.hostname=\u30db\u30b9\u30c8\u306e DNS \u540d\u307e\u305f\u306f IP \u30a2\u30c9\u30ec\u30b9\u3067\u3059\u3002 @@ -1344,7 +1344,7 @@ message.migrate.instance.to.ps=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9 message.migrate.router.confirm=\u30eb\u30fc\u30bf\u30fc\u306e\u79fb\u884c\u5148\u306f\u6b21\u306e\u30db\u30b9\u30c8\u3067\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.migrate.systemvm.confirm=\u30b7\u30b9\u30c6\u30e0 VM \u306e\u79fb\u884c\u5148\u306f\u6b21\u306e\u30db\u30b9\u30c8\u3067\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.migrate.volume=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u306b\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u79fb\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.new.user=\u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0081\u00ab\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0083\u00a6\u00e3\u0083\u00bc\u00e3\u0082\u00b6\u00e3\u0083\u00bc\u00e3\u0082\u0092\u00e8\u00bf\u00bd\u00e5\u008a\u00a0\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0080\u0081\u00e6\u00ac\u00a1\u00e3\u0081\u00ae\u00e6\u0083 +message.new.user=\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u65b0\u3057\u3044\u30e6\u30fc\u30b6\u30fc\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.no.network.support.configuration.not.true=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3 \u30b0\u30eb\u30fc\u30d7\u304c\u6709\u52b9\u306a\u30be\u30fc\u30f3\u304c\u7121\u3044\u305f\u3081\u3001\u8ffd\u52a0\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u6a5f\u80fd\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u624b\u9806 5. \u306b\u9032\u3093\u3067\u304f\u3060\u3055\u3044\u3002 message.no.network.support=\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3068\u3057\u3066 vSphere \u3092\u9078\u629e\u3057\u307e\u3057\u305f\u304c\u3001\u3053\u306e\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u306b\u8ffd\u52a0\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u6a5f\u80fd\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u624b\u9806 5. \u306b\u9032\u3093\u3067\u304f\u3060\u3055\u3044\u3002 message.no.projects.adminOnly=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002
    \u7ba1\u7406\u8005\u306b\u65b0\u3057\u3044\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4f5c\u6210\u3092\u4f9d\u983c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 @@ -1407,7 +1407,7 @@ message.tooltip.reserved.system.netmask=\u30dd\u30c3\u30c9\u306e\u30b5\u30d6\u30 message.tooltip.zone.name=\u30be\u30fc\u30f3\u306e\u540d\u524d\u3067\u3059\u3002 message.update.os.preference=\u3053\u306e\u30db\u30b9\u30c8\u306e OS \u57fa\u672c\u8a2d\u5b9a\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u540c\u69d8\u306e\u57fa\u672c\u8a2d\u5b9a\u3092\u6301\u3064\u3059\u3079\u3066\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306f\u3001\u5225\u306e\u30db\u30b9\u30c8\u3092\u9078\u629e\u3059\u308b\u524d\u306b\u307e\u305a\u3053\u306e\u30db\u30b9\u30c8\u306b\u5272\u308a\u5f53\u3066\u3089\u308c\u307e\u3059\u3002 message.update.resource.count=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30ea\u30bd\u30fc\u30b9\u6570\u3092\u66f4\u65b0\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.update.ssl=\u5404\u30b3\u30f3\u30bd\u30fc\u30eb \u30d7\u30ed\u30ad\u30b7\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u66f4\u65b0\u3059\u308b\u3001X.509 \u6e96\u62e0\u306e\u65b0\u3057\u3044 SSL \u8a3c\u660e\u66f8\u3092\u9001\u4fe1\u3057\u3066\u304f\u3060\u3055\u3044\: +message.update.ssl=\u5404\u30b3\u30f3\u30bd\u30fc\u30eb \u30d7\u30ed\u30ad\u30b7\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u66f4\u65b0\u3059\u308b\u3001X.509 \u6e96\u62e0\u306e\u65b0\u3057\u3044 SSL \u8a3c\u660e\u66f8\u3092\u9001\u4fe1\u3057\u3066\u304f\u3060\u3055\u3044: message.validate.instance.name=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u540d\u306f 63 \u6587\u5b57\u4ee5\u5185\u3067\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002ASCII \u6587\u5b57\u306e a\uff5ez\u3001A\uff5eZ\u3001\u6570\u5b57\u306e 0\uff5e9\u3001\u304a\u3088\u3073\u30cf\u30a4\u30d5\u30f3\u306e\u307f\u3092\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002\u6587\u5b57\u3067\u59cb\u307e\u308a\u3001\u6587\u5b57\u307e\u305f\u306f\u6570\u5b57\u3067\u7d42\u308f\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 message.virtual.network.desc=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u5c02\u7528\u4eee\u60f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3067\u3059\u3002\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8 \u30c9\u30e1\u30a4\u30f3\u306f VLAN \u5185\u306b\u914d\u7f6e\u3055\u308c\u3001\u30d1\u30d6\u30ea\u30c3\u30af \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3078\u306e\u30a2\u30af\u30bb\u30b9\u306f\u3059\u3079\u3066\u4eee\u60f3\u30eb\u30fc\u30bf\u30fc\u306b\u3088\u3063\u3066\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u3055\u308c\u307e\u3059\u3002 message.vm.create.template.confirm=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u3068 VM \u304c\u81ea\u52d5\u7684\u306b\u518d\u8d77\u52d5\u3055\u308c\u307e\u3059\u3002 @@ -1418,9 +1418,9 @@ message.Zone.creation.complete=\u30be\u30fc\u30f3\u304c\u4f5c\u6210\u3055\u308c\ message.zone.creation.complete.would.you.like.to.enable.this.zone=\u30be\u30fc\u30f3\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u3053\u306e\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.zone.no.network.selection=\u9078\u629e\u3057\u305f\u30be\u30fc\u30f3\u3067\u306f\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e\u3067\u304d\u307e\u305b\u3093\u3002 message.zone.step.1.desc=\u30be\u30fc\u30f3\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30e2\u30c7\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.zone.step.2.desc=\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084Zone\u00e3\u0082\u0092\u00e8\u00bf\u00bd\u00e5\u008a\u00a0\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0080\u0081\u00e6\u00ac\u00a1\u00e3\u0081\u00ae\u00e6\u0083 -message.zone.step.3.desc=\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084Pod\u00e3\u0082\u0092\u00e8\u00bf\u00bd\u00e5\u008a\u00a0\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0080\u0081\u00e6\u00ac\u00a1\u00e3\u0081\u00ae\u00e6\u0083 -message.zoneWizard.enable.local.storage=\u8b66\u544a\: \u3053\u306e\u30be\u30fc\u30f3\u306e\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408\u306f\u3001\u30b7\u30b9\u30c6\u30e0 VM \u306e\u8d77\u52d5\u5834\u6240\u306b\u5fdc\u3058\u3066\u6b21\u306e\u64cd\u4f5c\u304c\u5fc5\u8981\u3067\u3059\u3002

    1. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4f5c\u6210\u3057\u305f\u5f8c\u3067\u30be\u30fc\u30f3\u306b\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u307e\u305f\u3001\u7121\u52b9\u72b6\u614b\u306e\u30be\u30fc\u30f3\u3092\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u3082\u3042\u308a\u307e\u3059\u3002

    2. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001system.vm.use.local.storage \u3092 true \u306b\u8a2d\u5b9a\u3057\u3066\u304b\u3089\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002


    \u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? +message.zone.step.2.desc=\u65b0\u3057\u3044\u30be\u30fc\u30f3\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +message.zone.step.3.desc=\u65b0\u3057\u3044\u30dd\u30c3\u30c9\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +message.zoneWizard.enable.local.storage=\u8b66\u544a: \u3053\u306e\u30be\u30fc\u30f3\u306e\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408\u306f\u3001\u30b7\u30b9\u30c6\u30e0 VM \u306e\u8d77\u52d5\u5834\u6240\u306b\u5fdc\u3058\u3066\u6b21\u306e\u64cd\u4f5c\u304c\u5fc5\u8981\u3067\u3059\u3002

    1. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4f5c\u6210\u3057\u305f\u5f8c\u3067\u30be\u30fc\u30f3\u306b\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u307e\u305f\u3001\u7121\u52b9\u72b6\u614b\u306e\u30be\u30fc\u30f3\u3092\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u3082\u3042\u308a\u307e\u3059\u3002

    2. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001system.vm.use.local.storage \u3092 true \u306b\u8a2d\u5b9a\u3057\u3066\u304b\u3089\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002


    \u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? mode=\u30e2\u30fc\u30c9 network.rate=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u901f\u5ea6 notification.reboot.instance=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u518d\u8d77\u52d5 diff --git a/ui/index.jsp b/ui/index.jsp index 8f31740a039..2992afb5c31 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -15,7 +15,7 @@ software distributed under the License is distributed on an KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---%> +--%><%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> From 6758d727a4b61e2e7a185c404cddf203876b560a Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Mon, 27 May 2013 09:05:04 +0200 Subject: [PATCH 157/201] debian: Package server.xml and tomcat6.conf This are symlinks to server-nonssl.xml and tomcat6-nonssl.conf, but they are required for starting the management server. Commit 2db7a4559e64e34b5c707157db240a1be322cb69 broke this. --- debian/cloudstack-management.install | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install index 2cc3e925970..a1325cdb2b5 100644 --- a/debian/cloudstack-management.install +++ b/debian/cloudstack-management.install @@ -15,20 +15,22 @@ # specific language governing permissions and limitations # under the License. -/etc/cloudstack/management/server-ssl.xml /etc/cloudstack/management/catalina.policy /etc/cloudstack/management/catalina.properties /etc/cloudstack/management/cloudmanagementserver.keystore /etc/cloudstack/management/logging.properties /etc/cloudstack/management/commands.properties /etc/cloudstack/management/ehcache.xml -/etc/cloudstack/management/tomcat6-nonssl.conf /etc/cloudstack/management/componentContext.xml /etc/cloudstack/management/applicationContext.xml +/etc/cloudstack/management/server-ssl.xml /etc/cloudstack/management/server-nonssl.xml +/etc/cloudstack/management/server.xml /etc/cloudstack/management/classpath.conf /etc/cloudstack/management/db.properties /etc/cloudstack/management/tomcat6-ssl.conf +/etc/cloudstack/management/tomcat6-nonssl.conf +/etc/cloudstack/management/tomcat6.conf /etc/cloudstack/management/web.xml /etc/cloudstack/management/environment.properties /etc/cloudstack/management/nonossComponentContext.xml From a16b707250fde01f24c9ab6f11189b630dd70962 Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Thu, 23 May 2013 20:15:35 +0900 Subject: [PATCH 158/201] CLOUDSTACK-2327: make cloud-setup-agent ovs aware Ovs brcompat will be obsolete, so if network.bridge.type was set to openvswitch, we'll use ovs command explicitly. Signed-off-by: Hiroaki KAWAI --- agent/bindir/cloud-setup-agent.in | 5 +- python/lib/cloudutils/globalEnv.py | 2 + python/lib/cloudutils/networkConfig.py | 14 ++++-- python/lib/cloudutils/serviceConfig.py | 66 +++++++++++++++++++++----- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in index 5e2ba09406d..d6f481db2e0 100755 --- a/agent/bindir/cloud-setup-agent.in +++ b/agent/bindir/cloud-setup-agent.in @@ -95,6 +95,9 @@ if __name__ == '__main__': parser.add_option("--prvNic", dest="prvNic", help="Private traffic interface") parser.add_option("--guestNic", dest="guestNic", help="Guest traffic interface") + old_config = configFileOps("@AGENTSYSCONFDIR@/agent.properties") + glbEnv.bridgeType = old_config.getEntry("network.bridge.type").lower() + (options, args) = parser.parse_args() if options.auto is None: userInputs = getUserInputs() @@ -104,7 +107,7 @@ if __name__ == '__main__': glbEnv.pod = userInputs[3] glbEnv.cluster = userInputs[4] #generate UUID - glbEnv.uuid = configFileOps("@AGENTSYSCONFDIR@/agent.properties").getEntry("guid") + glbEnv.uuid = old_config.getEntry("guid") if glbEnv.uuid == "": glbEnv.uuid = bash("uuidgen").getStdout() else: diff --git a/python/lib/cloudutils/globalEnv.py b/python/lib/cloudutils/globalEnv.py index 94d981f4dab..867aa17670d 100644 --- a/python/lib/cloudutils/globalEnv.py +++ b/python/lib/cloudutils/globalEnv.py @@ -40,3 +40,5 @@ class globalEnv: self.privateNet = "cloudbr0" #distribution self.distribution = None + # bridgeType + self.bridgeType = "native" diff --git a/python/lib/cloudutils/networkConfig.py b/python/lib/cloudutils/networkConfig.py index b6b729a4fec..9e456e970be 100644 --- a/python/lib/cloudutils/networkConfig.py +++ b/python/lib/cloudutils/networkConfig.py @@ -19,6 +19,7 @@ from cloudException import CloudRuntimeException, CloudInternalException import logging import os import re +import subprocess class networkConfig: class devInfo: @@ -85,15 +86,22 @@ class networkConfig: @staticmethod def isNetworkDev(devName): - return os.path.exists("/sys/class/net/%s"%devName) + return os.path.exists("/sys/class/net/%s" % devName) @staticmethod def isBridgePort(devName): - return os.path.exists("/sys/class/net/%s/brport"%devName) + return os.path.exists("/sys/class/net/%s/brport" % devName) @staticmethod def isBridge(devName): - return os.path.exists("/sys/class/net/%s/bridge"%devName) + return os.path.exists("/sys/class/net/%s/bridge" % devName) + + @staticmethod + def isOvsBridge(devName): + try: + return 0==subprocess.check_call(("ovs-vsctl", "br-exists", devName)) + except subprocess.CalledProcessError: + return False @staticmethod def getBridge(devName): diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py index 1e32d0f3b0f..d129e00c45b 100755 --- a/python/lib/cloudutils/serviceConfig.py +++ b/python/lib/cloudutils/serviceConfig.py @@ -94,8 +94,10 @@ class networkConfigBase: if not self.netcfg.isNetworkDev(br): logging.debug("%s is not a network device, is it down?"%br) return False - if not self.netcfg.isBridge(br): - raise CloudInternalException("%s is not a bridge"%br) + if self.syscfg.env.bridgeType == "openvswitch" and not self.netcfg.isOvsBridge(br): + raise CloudInternalException("%s is not an openvswitch bridge" % br) + if self.syscfg.env.bridgeType == "native" and not self.netcfg.isBridge(br): + raise CloudInternalException("%s is not a bridge" % br) preCfged = True return preCfged @@ -153,11 +155,28 @@ class networkConfigUbuntu(serviceCfgBase, networkConfigBase): match = re.match("^ *iface %s.*"%dev.name, line) if match is not None: dev.method = self.getNetworkMethod(match.group(0)) - bridgeCfg = "\niface %s inet manual\n \ - auto %s\n \ - iface %s inet %s\n \ - bridge_ports %s\n"%(dev.name, br, br, dev.method, dev.name) cfo = configFileOps(self.netCfgFile, self) + if self.syscfg.env.bridgeType == "openvswitch": + bridgeCfg = "\n".join(("", + "iface {device} inet manual", + " ovs_type OVSPort", + " ovs_bridge {bridge}", + "", + "auto {bridge}", + "allow-ovs {bridge}", + "iface {bridge} inet {device_method}", + " ovs_type OVSBridge", + " ovs_ports {device}", + "")).format(bridge=br, device=dev.name, device_method=dev.method) + cfo.replace_line("^ *auto %s.*" % dev.name, + "allow-{bridge} {device}".format(bridge=br, device=dev.name)) + elif self.syscfg.env.bridgeType == "native": + bridgeCfg = "\niface %s inet manual\n \ + auto %s\n \ + iface %s inet %s\n \ + bridge_ports %s\n"%(dev.name, br, br, dev.method, dev.name) + else: + raise CloudInternalException("Unknown network.bridge.type %s" % self.syscfg.env.bridgeType) cfo.replace_line("^ *iface %s.*"%dev.name, bridgeCfg) def addDev(self, br, dev): @@ -193,8 +212,9 @@ class networkConfigUbuntu(serviceCfgBase, networkConfigBase): self.syscfg.svo.stopService("network-manager") self.syscfg.svo.disableService("network-manager") - if not bash("ifup %s"%self.brName).isSuccess(): - raise CloudInternalException("Can't start network:%s"%self.brName, bash.getErrMsg(self)) + ifup_op = bash("ifup %s"%self.brName) + if not ifup_op.isSuccess(): + raise CloudInternalException("Can't start network:%s %s" % (self.brName, ifup_op.getErrMsg())) self.syscfg.env.nics.append(self.brName) self.syscfg.env.nics.append(self.brName) @@ -222,8 +242,8 @@ class networkConfigRedhat(serviceCfgBase, networkConfigBase): networkConfigBase.__init__(self, syscfg) def writeToCfgFile(self, brName, dev): - self.devCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s"%dev.name - self.brCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s"%brName + self.devCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s" % dev.name + self.brCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s" % brName isDevExist = os.path.exists(self.devCfgFile) isBrExist = os.path.exists(self.brCfgFile) @@ -241,7 +261,7 @@ class networkConfigRedhat(serviceCfgBase, networkConfigBase): def addBridge(self, brName, dev): - bash("ifdown %s"%dev.name) + bash("ifdown %s" % dev.name) if not os.path.exists(self.brCfgFile): shutil.copy(self.devCfgFile, self.brCfgFile) @@ -250,14 +270,34 @@ class networkConfigRedhat(serviceCfgBase, networkConfigBase): cfo = configFileOps(self.devCfgFile, self) cfo.addEntry("NM_CONTROLLED", "no") cfo.addEntry("ONBOOT", "yes") - cfo.addEntry("BRIDGE", brName) + if self.syscfg.env.bridgeType == "openvswitch": + if cfo.getEntry("IPADDR"): + cfo.rmEntry("IPADDR", cfo.getEntry("IPADDR")) + cfo.addEntry("DEVICETYPE", "ovs") + cfo.addEntry("TYPE", "OVSPort") + cfo.addEntry("OVS_BRIDGE", brName) + elif self.syscfg.env.bridgeType == "native": + cfo.addEntry("BRIDGE", brName) + else: + raise CloudInternalException("Unknown network.bridge.type %s" % self.syscfg.env.bridgeType) cfo.save() cfo = configFileOps(self.brCfgFile, self) cfo.addEntry("NM_CONTROLLED", "no") cfo.addEntry("ONBOOT", "yes") cfo.addEntry("DEVICE", brName) - cfo.addEntry("TYPE", "Bridge") + if self.syscfg.env.bridgeType == "openvswitch": + if cfo.getEntry("HWADDR"): + cfo.rmEntry("HWADDR", cfo.getEntry("HWADDR")) + if cfo.getEntry("UUID"): + cfo.rmEntry("UUID", cfo.getEntry("UUID")) + cfo.addEntry("STP", "yes") + cfo.addEntry("DEVICETYPE", "ovs") + cfo.addEntry("TYPE", "OVSBridge") + elif self.syscfg.env.bridgeType == "native": + cfo.addEntry("TYPE", "Bridge") + else: + raise CloudInternalException("Unknown network.bridge.type %s" % self.syscfg.env.bridgeType) cfo.save() def config(self): From cc2866c1ea2c778d434e416f8a7183bd3c10c518 Mon Sep 17 00:00:00 2001 From: Mice Xia Date: Mon, 27 May 2013 15:47:56 +0800 Subject: [PATCH 159/201] CLOUDSTACK-2686 Upload volume to project is not shown in project storage view --- .../api/command/user/volume/UploadVolumeCmd.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java index 3b00ba0d4bb..fea3e04d249 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java @@ -22,7 +22,9 @@ import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; @@ -72,6 +74,10 @@ public class UploadVolumeCmd extends BaseAsyncCmd { description="Image store uuid") private String imageStoreUuid; + @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, + description="Upload volume for the project") + private Long projectId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -135,7 +141,7 @@ public class UploadVolumeCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = finalyzeAccountId(accountName, domainId, null, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } From 08ac8fb4687fb14cf9524a022527a64e033be9ab Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Mon, 27 May 2013 14:02:17 +0530 Subject: [PATCH 160/201] CLOUDSTACK-2688 Add DB index to Alert.last_sent column to speed up listAlertsCmd. --- .../cloud/upgrade/dao/Upgrade410to420.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index e7f47331eab..16ab05cea06 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -28,6 +28,8 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import com.cloud.network.vpc.NetworkACL; @@ -77,6 +79,34 @@ public class Upgrade410to420 implements DbUpgrade { updateNetworksForPrivateGateways(conn); removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); fix22xKVMSnapshots(conn); + addIndexForAlert(conn); + } + + private void addIndexForAlert(Connection conn) { + + //First drop if it exists. (Due to patches shipped to customers some will have the index and some wont.) + List indexList = new ArrayList(); + s_logger.debug("Dropping index i_alert__last_sent if it exists"); + indexList.add("i_alert__last_sent"); + DbUpgradeUtils.dropKeysIfExist(conn, "alert", indexList, false); + + //Now add index. + PreparedStatement pstmt = null; + try { + pstmt = conn.prepareStatement("ALTER TABLE `cloud`.`alert` ADD INDEX `i_alert__last_sent`(`last_sent`)"); + pstmt.executeUpdate(); + s_logger.debug("Added index i_alert__last_sent for table alert"); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to add index i_alert__last_sent to alert table for the column last_sent", e); + } finally { + try { + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } private void updateSystemVmTemplates(Connection conn) { From a688d631047ae7dc70a4c4d8c5330dec1dc1cd95 Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Mon, 27 May 2013 14:16:16 +0530 Subject: [PATCH 161/201] CLOUDSTACK-2689 Create volume after upgrade from snapshot taken in 2.2.14 deletes the snapshot physically from sec. storage. Added DB upgrade sql to make swift_id NULL if they are set to 0 --- setup/db/db/schema-410to420.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 435bb83d3c9..1c9a8c1bddc 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1709,6 +1709,8 @@ update `cloud`.`vpc_gateways` set network_acl_id = 2; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'VpcManager', 'blacklisted.routes', NULL, 'Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway'); +UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0; + -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; From fac59a742913e347fb090d46fe75d80c3fda122f Mon Sep 17 00:00:00 2001 From: Milamber Date: Mon, 27 May 2013 09:56:52 +0100 Subject: [PATCH 162/201] Update L10N strings from Transifex to repo --- .../classes/resources/messages_ar.properties | 2 +- .../classes/resources/messages_ca.properties | 1 - .../resources/messages_de_DE.properties | 1 - .../classes/resources/messages_es.properties | 1 - .../resources/messages_fr_FR.properties | 5 +- .../resources/messages_it_IT.properties | 191 +++++++++++++++++- .../resources/messages_ko_KR.properties | 4 +- .../resources/messages_nb_NO.properties | 1 - .../resources/messages_pt_BR.properties | 2 +- .../resources/messages_ru_RU.properties | 4 +- .../resources/messages_zh_CN.properties | 10 +- 11 files changed, 211 insertions(+), 11 deletions(-) diff --git a/client/WEB-INF/classes/resources/messages_ar.properties b/client/WEB-INF/classes/resources/messages_ar.properties index 4d3011b5a6c..5b3afea929d 100644 --- a/client/WEB-INF/classes/resources/messages_ar.properties +++ b/client/WEB-INF/classes/resources/messages_ar.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\u062a\u063a\u064a\u0631 \u062e\u0635\u0627\u0626\u0635 \u0627\u0644\u0639\u0646\u0635\u0631 confirm.enable.s3=\u0641\u0636\u0644\u0627 \u0642\u0645 \u0628\u062a\u0639\u0628\u0626\u0629 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0642\u0627\u062f\u0645\u0629 \u0644\u062a\u0645\u0643\u064a\u0646 \u0627\u0644\u062a\u062e\u0632\u064a\u0646 S3 \u0644\u0644\u0630\u0627\u0643\u0631\u0629 \u0627\u0644\u062b\u0627\u0646\u0648\u064a\u0629. instances.actions.reboot.label=\u0625\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0646\u0645\u0648\u0630\u062c @@ -217,6 +216,7 @@ label.zone.step.3.title=\u0627\u0644\u062e\u0637\u0648\u0629 3 \\\: \u0639\u0644 label.zone.step.4.title=\u0627\u0644\u062e\u0637\u0648\u0629 4 \\\: <\u0642\u0648\u064a> \u0625\u0636\u0627\u0641\u0629 \u0645\u062c\u0645\u0648\u0639\u0629 IP <\\\u0642\u0648\u064a> label.zone.wide=\u0645\u0646\u0637\u0642\u0629 \u0648\u0627\u0633\u0639\u0629 label.zoneWizard.trafficType.guest=\u0627\u0644\u0636\u064a\u0641 \\\: \u0627\u0644\u062d\u0631\u0643\u0629 \u0628\u064a\u0646 \u0627\u0644\u0623\u062c\u0647\u0632\u0629 \u0627\u0644\u0625\u0641\u062a\u0631\u0627\u0636\u064a\u0629 \u0644\u0644\u0645\u0633\u062a\u062e\u062f\u0645 \u0627\u0644\u0646\u0647\u0627\u0626\u064a. +label.zoneWizard.trafficType.management=\u0625\u062f\u0627\u0631\u0629\\\: \u0627\u0644\u062d\u0631\u0643\u0629 \u0628\u064a\u0646 \u0627\u0644\u0645\u0648\u0627\u0631\u062f \u0627\u0644\u062f\u0627\u062e\u0644\u064a\u0629 \u0644 \u0643\u0644\u0627\u0648\u062f \u0633\u062a\u0627\u0643 \u060c \u0645\u062a\u0636\u0645\u0646\u0629 \u0623\u064a \u062c\u0632\u0621 \u064a\u062a\u0635\u0644 \u0628\u062e\u0627\u062f\u0645\\\u0633\u064a\u0631\u0641\u0631 \u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u060c \u0645\u062b\u0644 \u0627\u0644\u0645\u0636\u064a\u0641\u0627\u062a \u0648 \u0623\u0646\u0638\u0645\u0629 \u0643\u0644\u0627\u0648\u062f \u0633\u062a\u0627\u0643 \u0627\u0644\u0625\u0641\u062a\u0631\u0627\u0636\u064a\u0629. label.zoneWizard.trafficType.public=\u0627\u0644\u0639\u0627\u0645\u0629 \\\: \u0627\u0644\u0645\u0631\u0648\u0631 \u0628\u064a\u0646 \u0627\u0644\u0625\u0646\u062a\u0631\u0646\u062a \u0648\u0627\u0644\u0623\u062c\u0647\u0632\u0629 \u0627\u0644\u0638\u0627\u0647\u0631\u064a\u0629 \u0641\u064a \u0627\u0644\u0633\u062d\u0627\u0628\u0629. label.zoneWizard.trafficType.storage=\u0627\u0644\u062a\u062e\u0632\u064a\u0646 \\\: \u0627\u0644\u0645\u0631\u0648\u0631 \u0628\u064a\u0646 \u0645\u0644\u0642\u0645\u0627\u062a \u0627\u0644\u062a\u062e\u0632\u064a\u0646 \u0627\u0644\u0627\u0628\u062a\u062f\u0627\u0626\u064a\u0629 \u0648\u0627\u0644\u062b\u0627\u0646\u0648\u064a\u0629\u060c \u0645\u062b\u0644 \u0642\u0648\u0627\u0644\u0628 VM \u0648\u0627\u0644\u0644\u0642\u0637\u0627\u062a message.acquire.new.ip.vpc=\u064a\u0631\u062c\u0649 \u0627\u0644\u062a\u0623\u0643\u064a\u062f \u0628\u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u0627\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0628\u0648\u0631\u062a\u0648\u0643\u0648\u0644 \u0625\u0646\u062a\u0631\u0646\u062a \u062c\u062f\u064a\u062f \u0644\u0647\u0630\u0627 \u0627\u0644\u062d\u0627\u0633\u0648\u0628 \u0627\u0644\u0625\u0641\u062a\u0631\u0627\u0636\u064a. diff --git a/client/WEB-INF/classes/resources/messages_ca.properties b/client/WEB-INF/classes/resources/messages_ca.properties index 4e66083dbd5..2d8e953419f 100644 --- a/client/WEB-INF/classes/resources/messages_ca.properties +++ b/client/WEB-INF/classes/resources/messages_ca.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - confirm.enable.swift=Si us plau ompliu la seg\u00fcent informaci\u00f3 per habilitar el suport per a Swift error.installWizard.message=Quelcom ha fallat, vost\u00e8 pot tornar enrere i corregir els errors detalls suggerime error.password.not.match=Els camps de contrasenya no coincideixen diff --git a/client/WEB-INF/classes/resources/messages_de_DE.properties b/client/WEB-INF/classes/resources/messages_de_DE.properties index ca87323cc77..3c0c8deaabd 100644 --- a/client/WEB-INF/classes/resources/messages_de_DE.properties +++ b/client/WEB-INF/classes/resources/messages_de_DE.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - error.installWizard.message=Ein Fehler ist aufgetreten; Sie k\u00f6nnen zur\u00fcckgehen und den Fehler korregieren error.login=Ihr Benutzername / Passwort stimmt nicht mit uneren unseren Aufzeichnungen \u00fcberein. error.session.expired=Ihre Sitzung ist abgelaufen. diff --git a/client/WEB-INF/classes/resources/messages_es.properties b/client/WEB-INF/classes/resources/messages_es.properties index 16cfc1cda49..86eb596689c 100644 --- a/client/WEB-INF/classes/resources/messages_es.properties +++ b/client/WEB-INF/classes/resources/messages_es.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - error.installWizard.message=Algo salio mal, debes ir para atr\u00e1s y corregir los error. error.login=Su nombre de usuario / contrase\u00c3\u00b1a no coincide con nuestros registros. error.mgmt.server.inaccessible=El Servidor de Gesti\u00c3\u00b3n es inaccesible. Por favor, int\u00c3\u00a9ntelo de nuevo m\u00c3\u00a1s tarde. diff --git a/client/WEB-INF/classes/resources/messages_fr_FR.properties b/client/WEB-INF/classes/resources/messages_fr_FR.properties index 8be438a11c1..33ffcfc4714 100644 --- a/client/WEB-INF/classes/resources/messages_fr_FR.properties +++ b/client/WEB-INF/classes/resources/messages_fr_FR.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Propri\u00e9t\u00e9s de l\\'\u00e9l\u00e9ment modifi\u00e9es confirm.enable.s3=Remplir les informations suivantes pour activer le support de stockage secondaire S3 confirm.enable.swift=Remplir les informations suivantes pour activer Swift @@ -93,6 +92,7 @@ label.action.delete.load.balancer=Supprimer la r\u00e8gle de r\u00e9partition de label.action.delete.network.processing=Suppression du r\u00e9seau... label.action.delete.network=Supprimer le r\u00e9seau label.action.delete.nexusVswitch=Supprimer le Nexus 1000v +label.action.delete.nic=Supprimer carte NIC label.action.delete.physical.network=Supprimer le r\u00e9seau physique label.action.delete.pod.processing=Suppression du pod... label.action.delete.pod=Supprimer le Pod @@ -1200,6 +1200,7 @@ message.action.delete.ISO.for.all.zones=L\\'ISO est utilis\u00e9 par toutes les message.action.delete.ISO=\u00cates-vous s\u00fbr que vous souhaitez supprimer cette ISO. message.action.delete.network=\u00cates-vous s\u00fbr que vous voulez supprimer ce r\u00e9seau. message.action.delete.nexusVswitch=Confirmer la suppession de ce Nexus 1000v +message.action.delete.nic=Veuillez confirmer que vous souhaitez supprimer cette carte NIC, ce qui supprimera \u00e9galement le r\u00e9seau associ\u00e9 sur la machine virtuelle. message.action.delete.physical.network=Confirmer la suppression du r\u00e9seau physique message.action.delete.pod=\u00cates-vous s\u00fbr que vous souhaitez supprimer ce pod. message.action.delete.primary.storage=\u00cates-vous s\u00fbr que vous voulez supprimer ce stockage principal. @@ -1412,6 +1413,7 @@ message.migrate.router.confirm=Confirmer la migration du routeur vers \: message.migrate.systemvm.confirm=Confirmer la migration de la VM syst\u00e8me vers \: message.migrate.volume=Confirmer la migration du volume vers un autre stockage principal. message.new.user=Renseigner les informations suivantes pour ajouter un nouveau compte utilisateur +message.no.affinity.groups=Vous n\\'avez pas de groupes d\\'affinit\u00e9. Continuer vers la prochaine \u00e9tape. message.no.network.support.configuration.not.true=Il n\\'y a pas de zone avec la fonction groupe de s\u00e9curit\u00e9 active. D\u00e8s lors, pas de fonction r\u00e9seau suppl\u00e9mentaires disponibles. Continuer \u00e0 l\\'\u00e9tape 5. message.no.network.support=S\u00e9lectionnez l\\'hyperviseur. vSphere, n\\'a pas de fonctionnalit\u00e9s suppl\u00e9mentaires pour le r\u00e9seau. Continuez \u00e0 l\\'\u00e9tape 5. message.no.projects.adminOnly=Vous n\\'avez pas de projet.
    Contacter votre administrateur pour ajouter un projet. @@ -1444,6 +1446,7 @@ message.restart.mgmt.usage.server=Red\u00e9marrer le ou les serveur(s) de gestio message.restart.network=Tous les services fournit par ce routeur virtuel vont \u00eatre interrompus. Confirmer le red\u00e9marrage de ce routeur. message.restart.vpc=Confirmer le red\u00e9marrage du VPC message.security.group.usage=(Utilisez Ctrl-clic pour s\u00e9lectionner les groupes de s\u00e9curit\u00e9 vis\u00e9s) +message.select.affinity.groups=S\u00e9lectionner les groupes d\\'affinit\u00e9 qui appartiendront \u00e0 cette machine virtuelle \: message.select.a.zone=Une zone correspond typiquement \u00e0 un seul centre de donn\u00e9es. Des zones multiples peuvent permettre de rendre votre cloud plus fiable en apportant une isolation physique et de la redondance. message.select.instance=S\u00e9lectionner une instance. message.select.iso=S\u00e9lectionner un ISO pour votre nouvelle instance virtuelle. diff --git a/client/WEB-INF/classes/resources/messages_it_IT.properties b/client/WEB-INF/classes/resources/messages_it_IT.properties index 78323b02578..6ae5bd85376 100644 --- a/client/WEB-INF/classes/resources/messages_it_IT.properties +++ b/client/WEB-INF/classes/resources/messages_it_IT.properties @@ -15,32 +15,207 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Elementi delle propriet\u00e0 modificati confirm.enable.s3=Si prega di inserire i valori richiesti per abilitare il supporto per il Secondary Storage di tipo S3 confirm.enable.swift=Si prega di inserire i valori richiesti per abilitare il supporto per Swift error.could.not.enable.zone=Impossibile abilitare la zona error.installWizard.message=E\\' stato rilevato un errore\: tornare agli step precedenti e correggere gli errori error.invalid.username.password=Username o Password non valida +error.login=Le credenziali fornite per username/password non corrispondono a quelle nei nostri sistemi. +error.menu.select=Impossibile effettuare operazioni senza aver selezionato alcun elemento. +error.mgmt.server.inaccessible=Impossibile accedere al Management Server. Si prega di riprovare pi\u00f9 tardi. error.password.not.match=I campi password non corrispondono error.please.specify.physical.network.tags=Le offerte di rete non sono disponibili se non si specificano tag per questa rete fisica. +error.session.expired=La sessione \u00e8 scaduta. error.something.went.wrong.please.correct.the.following=E\\' stato rilevato un errore; si prega di correggere quanto indicato di seguito error.unable.to.reach.management.server=Impossibile raggiungere il Management Server +error.unresolved.internet.name=Il tuo nome internet non pu\u00f2 essere risolto. +extractable=Estraibile +force.delete.domain.warning=Attenzione\: La scelta di questa opzione provocher\u00e0 la rimozione di tutti i sotto domini e agli account associati e alle loro risorse. +force.remove.host.warning=Attenzione\: La scelta di questa opzione provocher\u00e0 l\\'arresto forzato di tutte le virtual machine da parte di CloudStack prima di rimuovere questo host dal cluster. +force.stop.instance.warning=Attenzione\: Forzare un arresto su questa instanza dovrebbe essere l\\'ultima opzione. C\\'\u00e8 il rischio di perdita di dati e di un comportamento inconsistente dello stato della virtual machine. +ICMP.code=Codice ICMP +ICMP.type=Tipo ICMP +image.directory=Directory Immagine instances.actions.reboot.label=Riavviare una instanza label.accept.project.invitation=Accettare un invito ad un progetto +label.account=Account label.account.and.security.group=Account, Security group +label.account.id=ID dell\\'Account +label.account.name=Nome Account +label.account.specific=Specifico dell\\'Account +label.accounts=Utenti +label.acquire.new.ip=Acquisizione nuovo indirizzo IP +label.action.attach.disk=Collegamento di un Disco +label.action.attach.disk.processing=Collegamento Disco in corso... +label.action.attach.iso=Collegamento di una immagine ISO +label.action.attach.iso.processing=Collegamento immagine ISO in corso... +label.action.cancel.maintenance.mode=Annullamento dello stato di Maintenance Mode +label.action.cancel.maintenance.mode.processing=Cancellazione dello stato Maintenance Mode in corso... +label.action.change.password=Modifica della Password +label.action.change.service=Modificare Servizio +label.action.change.service.processing=Modifica del Servizio in corso... +label.action.copy.ISO=Copia della immagine ISO +label.action.copy.ISO.processing=Copia immagine ISO in corso... +label.action.copy.template=Copia di un Template +label.action.copy.template.processing=Copia Template in corso... +label.action.create.template=Creazione Template +label.action.create.template.from.vm=Creazione Template da una VM +label.action.create.template.from.volume=Creazione Template da un Volume +label.action.create.template.processing=Creazione Template in corso... +label.action.create.vm=Creazione VM +label.action.create.vm.processing=Creazione VM in corso... +label.action.create.volume=Creazione Volume +label.action.create.volume.processing=Creazione Volume in corso... +label.action.delete.account=Cancellazione account +label.action.delete.account.processing=Cancellazione account in corso.... +label.action.delete.cluster=Cancellazione Cluster +label.action.delete.cluster.processing=Cancellazione Cluster in corso.... +label.action.delete.disk.offering=Cancellazione Offerta Disco +label.action.delete.disk.offering.processing=Cancellazione Offerta Disco in corso.... +label.action.delete.domain=Cancellazione Dominio +label.action.delete.domain.processing=Cancellazione Dominio in corso.... +label.action.delete.firewall=Cancellazione regola firewall +label.action.delete.firewall.processing=Cancellazione Firewall in corso.... +label.action.delete.IP.range=Cancellazione intervallo indirizzi IP +label.action.delete.IP.range.processing=Cancellazione intervallo indirizzi IP in corso.... +label.action.delete.ISO=Cancellazione immagine ISO +label.action.delete.ISO.processing=Cancellazione immagine ISO in corso.... +label.action.delete.load.balancer=Cancellazione regola load balancer +label.action.delete.load.balancer.processing=Cancellazione Load Balancer in corso.... +label.action.delete.network=Cancellazione Rete +label.action.delete.network.processing=Cancellazione Rete in corso.... label.action.delete.nexusVswitch=Cancellare Nexus 1000v label.action.delete.physical.network=Cancellazione di una rete fisica +label.action.delete.pod=Cancellazione Pod +label.action.delete.pod.processing=Cancellazione Pod in corso.... +label.action.delete.primary.storage=Cancellazione Storage Primario +label.action.delete.primary.storage.processing=Cancellazione Storage Primario in corso.... +label.action.delete.secondary.storage=Cancellazione Storage Secondario +label.action.delete.secondary.storage.processing=Cancellazione Storage Secondario in corso.... +label.action.delete.security.group=Cancellazione Security Group +label.action.delete.security.group.processing=Cancellazione Security Group in corso.... +label.action.delete.service.offering=Cancellazione Offerta di Servizio +label.action.delete.service.offering.processing=Cancellazione Offerta di Servizio in corso.... +label.action.delete.snapshot=Cancellazione Snapshot +label.action.delete.snapshot.processing=Cancellazione Snapshot in corso.... label.action.delete.system.service.offering=Cancellare Offerta di Servizio di Sistema +label.action.delete.template=Cancellazione Template +label.action.delete.template.processing=Cancellazione Template in corso.... +label.action.delete.user=Cancellazione Utente +label.action.delete.user.processing=Cancellazione Utente in corso.... +label.action.delete.volume=Cancellazione Volume +label.action.delete.volume.processing=Cancellazione Volume in corso.... +label.action.delete.zone=Cancellazione Zona +label.action.delete.zone.processing=Cancellazione Zona in corso.... +label.action.destroy.instance.processing=Rimozione Instanza in corso.... +label.action.destroy.instance=Rimozione instanza +label.action.destroy.systemvm.processing=Rimozione VM di Sistema in corso.... +label.action.destroy.systemvm=Rimozione VM di sistema +label.action.detach.disk.processing=Scollegamento Disco in corso.... +label.action.detach.disk=Scollegamento di un Disco +label.action.detach.iso.processing=Scollegamento immagine ISO in corso.... +label.action.detach.iso=Scollegamento immagine ISO +label.action.disable.account=Disabilitazione account +label.action.disable.account.processing=Disabilitazione account in corso.... +label.action.disable.cluster=Disabilitazione Cluster +label.action.disable.cluster.processing=Disabilitazione Cluster in corso.... label.action.disable.nexusVswitch=Disabilitare Nexus 1000v label.action.disable.physical.network=Disabilitare la rete fisica +label.action.disable.pod=Disabilitazione Pod +label.action.disable.pod.processing=Disabilitazione Pod in corso.... +label.action.disable.static.NAT=Disabilitazione NAT Statico +label.action.disable.static.NAT.processing=Disabilitazione NAT Statico in corso.... +label.action.disable.user=Disabilitazione Utente +label.action.disable.user.processing=Disabilitazione Utente in corso.... +label.action.disable.zone=Disabilitazione Zona +label.action.disable.zone.processing=Disabilitazione Zona in corso.... +label.action.download.ISO=Download immagine ISO +label.action.download.template=Download Template +label.action.download.volume=Download Volume +label.action.download.volume.processing=Download Volume in corso.... +label.action.edit.account=Modifica account +label.action.edit.disk.offering=Modifica Offerta Disco +label.action.edit.domain=Modifica Dominio +label.action.edit.global.setting=Modifica Impostazioni Globali +label.action.edit.host=Modifica Host +label.action.edit.instance=Modifica Instanza +label.action.edit.ISO=Modifica immagine ISO +label.action.edit.network=Modifica Rete +label.action.edit.network.offering=Modifica Offerta di Rete +label.action.edit.network.processing=Modifica Rete in corso.... +label.action.edit.pod=Modifica Pod +label.action.edit.primary.storage=Modifica Storage Primario +label.action.edit.resource.limits=Modifica Limiti delle Risorse +label.action.edit.service.offering=Modifica Offerta di Servizio +label.action.edit.template=Modifica Template +label.action.edit.user=Modifica Utente +label.action.edit.zone=Modifica Zona +label.action.enable.account=Abilitazione account +label.action.enable.account.processing=Abilitazione account in corso.... +label.action.enable.cluster=Abilitazione Cluster +label.action.enable.cluster.processing=Abilitazione Cluster in corso.... +label.action.enable.maintenance.mode=Abilitazione dello stato Maintenance Mode +label.action.enable.maintenance.mode.processing=Abilitazione dello stato Maintenance Mode in corso.... label.action.enable.nexusVswitch=Abilitare Nexus 1000v label.action.enable.physical.network=Abilitare la rete fisica +label.action.enable.pod=Abilitazione Pod +label.action.enable.pod.processing=Abilitazione Pod in corso.... +label.action.enable.static.NAT=Abilitazione NAT Statico +label.action.enable.static.NAT.processing=Abilitazione NAT Statico in corso.... +label.action.enable.user=Abilitazione Utente +label.action.enable.user.processing=Abilitazione Utente in corso.... +label.action.enable.zone=Abilitazione Zona +label.action.enable.zone.processing=Abilitazione Zona in corso.... +label.action.force.reconnect.processing=Riconnessione in corso.... +label.action.generate.keys=Generazione Chiavi +label.action.generate.keys.processing=Generazione Chiavi in corso.... label.action.list.nexusVswitch=Elencare Nexus 1000v +label.action.lock.account=Blocco di un account +label.action.lock.account.processing=Blocco account in corso.... +label.action.manage.cluster=Gestione Cluster +label.action.manage.cluster.processing=Gestione Cluster in corso.... +label.action.migrate.instance=Migrazione Instanza +label.action.migrate.instance.processing=Migrazione Instanza in corso.... +label.action.migrate.router=Migrazione Router label.action.migrate.router.processing=Migrazione Router... +label.action.migrate.systemvm=Migrazione VM di Systema +label.action.migrate.systemvm.processing=Migrazione VM di Sistema in corso.... +label.action.reboot.instance.processing=Riavvio Instanza in corso.... +label.action.reboot.instance=Riavvio Instanza +label.action.reboot.router.processing=Riavvio Router in corso.... +label.action.reboot.router=Riavvio Router +label.action.reboot.systemvm.processing=Riavvio VM di Sistema in corso.... +label.action.reboot.systemvm=Riavvio VM di Sistema label.action.register.iso=Registrare una ISO label.action.register.template=Registrare un template +label.action.release.ip.processing=Rilascio indirizzo IP in corso.... +label.action.release.ip=Rilascio indirizzo IP +label.action.remove.host.processing=Rimozione Host in corso.... +label.action.remove.host=Rimozione Host +label.action.reset.password.processing=Reset della Password in corso.... +label.action.reset.password=Reset Password +label.action.resize.volume.processing=Ridimensionamento Volume in corso.... +label.action.resize.volume=Ridimensionamento Volume +label.action.restore.instance.processing=Restore dell\\'Instanza in corso.... +label.action.restore.instance=Restore Instanza +label.actions=Azioni +label.action.start.instance=Avvio Instanza +label.action.start.instance.processing=Avvio Instanza in corso.... +label.action.start.router=Avvio Router +label.action.start.router.processing=Avvio Router in corso.... +label.action.start.systemvm=Avvio VM di Sistema +label.action.start.systemvm.processing=Avvio VM di Sistema in corso.... +label.action.stop.instance=Arresto Instanza +label.action.stop.instance.processing=Arresto Instanza in corso.... +label.action.stop.router=Arresto Router +label.action.stop.router.processing=Arresto Router in corso.... +label.action.stop.systemvm=Arresto VM di Sistema +label.action.stop.systemvm.processing=Arresto VM di Sistema in corso.... +label.action.update.OS.preference=Aggiornamento Preferenze OS +label.action.update.OS.preference.processing=Aggiornamento preferenze OS in corso.... label.activate.project=Attivare il Progetto +label.active.sessions=Sessioni Attive label.add.accounts=Aggiungere utenti label.add.accounts.to=Aggiungere utenti a label.add.account.to.project=Aggiungere account al progetto @@ -49,6 +224,7 @@ label.add.compute.offering=Aggiungere una offerta computazionale label.add.egress.rule=Aggiungere una regola d\\'uscita label.add.F5.device=Aggiungere device F5 label.add.guest.network=Aggiungere una rete guest +label.additional.networks=Network Aggiuntivi label.add.netScaler.device=Aggiungere device Netscaler label.add.network.ACL=Aggiungere le ACL di rete label.add.network.offering=Aggiungere offerta di rete @@ -76,22 +252,32 @@ label.add.vpn.customer.gateway=Aggiungere Gateway VPN del Cliente label.add.VPN.gateway=Aggiungere un Gateway VPN label.add.vpn.user=Aggiungere utente VPN label.advanced=Avanzato +label.advanced.search=Ricerca Avanzata label.agent.password=Password per l\\'Agent label.agent.username=Username per l\\'Agent label.allocated=Allocato label.apply=Applicare label.associated.network=Rete Associata +label.available.public.ips=Indirizzi IP Pubblici Disponibili label.bandwidth=Capacit\u00e0 della banda (Bandwidth) label.basic=Basic label.broadcast.uri=URI di Broadcast +label.cancel=Annulla +label.certificate=Certificato label.change.service.offering=Modificare offerta di servizio +label.character=Carattere label.checksum=Checksum MD5 +label.cidr=CIDR label.CIDR.list=Lista CIDR label.CIDR.of.destination.network=Valore CIDR della rete di destinazione label.clear.list=Pulizia dell\\'elenco +label.cloud.console=Console di Gestione Cloud label.cluster=Cluster label.cluster.name=Nome del Cluster label.clusters=Cluster +label.cluster.type=Tipo di Cluster +label.clvm=CLVM +label.code=Codice label.community=Community label.compute.and.storage=Computazione e Storage label.compute=Compute @@ -107,6 +293,7 @@ label.console.proxy=Proxy di Console label.continue.basic.install=Proseguire con l\\'installazione di base label.continue=Continuare label.corrections.saved=Salvataggio correzioni effettuato +label.cpu=CPU label.cpu.mhz=CPU (in MHz) label.created.by.system=Creato dal sistema label.create.project=Creare un progetto @@ -234,6 +421,7 @@ label.max.volumes=Numero max di volumi label.max.vpcs=Numero max di VPC label.may.continue=E\\' ora possibile continuare. label.memory.mb=Memoria (in MB) +label.menu.accounts=Utenti label.menu.configuration=Configurazione label.menu.infrastructure=Infrastruttura label.menu.system.service.offerings=Offerte di Sistema @@ -433,6 +621,7 @@ label.zone.name=Nome Zona label.zones=Zone label.zone.type=Tipo di Zona label.zoneWizard.trafficType.guest=Guest\: Traffico di rete tra le virtual machine dell\\'utente finale +label.zoneWizard.trafficType.management=Management\: Traffico di rete tra le risorse interne di CloudStack, incluso qualsiasi componente che comunichi con il Management Server, come ad esempio gli host e le VM di Sistema di CloudStack label.zoneWizard.trafficType.public=Public\: Traffico di rete tra la rete internet e le virtual machine nell\\'infrastruttura cloud. label.zoneWizard.trafficType.storage=Storage\: Traffico di rete tra i server di primary e secondary storage, come ad esempio i template delle VM e le operazioni di snapshot message.acquire.new.ip=Si prega di confermare di voler acquisire un nuovo indirizzo IP per questa rete. diff --git a/client/WEB-INF/classes/resources/messages_ko_KR.properties b/client/WEB-INF/classes/resources/messages_ko_KR.properties index 766fc607648..757871acde0 100644 --- a/client/WEB-INF/classes/resources/messages_ko_KR.properties +++ b/client/WEB-INF/classes/resources/messages_ko_KR.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\ud56d\ubaa9 \uc18d\uc131 \ubcc0\uacbd confirm.enable.swift=Swift \uae30\uc220 \uc9c0\uc6d0\ub97c \uc0ac\uc6a9 \ud558\ub824\uba74 \ub2e4\uc74c \uc815\ubcf4\ub97c \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624. error.could.not.enable.zone=Zone\uc744 \uc0ac\uc6a9 \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. @@ -1194,6 +1193,7 @@ message.add.load.balancer.under.ip=\ub2e4\uc74c IP \uc8fc\uc18c\uc5d0 \ub300\ud5 message.add.load.balancer=Zone\uc5d0 \ub124\ud2b8\uc6cc\ud06c \ub85c\ub4dc \uacf5\uc720 \uc7a5\uce58\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.network=Zone \uc5d0 \uc0c8\ub85c\uc6b4 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.new.gateway.to.vpc=\ud604\uc7ac VPC\uc5d0 \uc0c8\ub85c\uc6b4 \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c \ucd94\uac00\ud558\uae30 \uc704\ud55c \uc815\ubcf4\ub97c \uc9c0\uc815\ud574 \uc8fc\uc2ed\uc2dc\uc624. +message.add.pod.during.zone.creation=\uac01 Zone\uc5d0\ub294 \ud55c \uac1c \uc774\uc0c1 Pod\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 Pod\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. Pod\ub294 \ud638\uc2a4\ud2b8\uc640 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uc5d0\uc11c \uad6c\uc131\ud569\ub2c8\ub2e4\ub9cc \uc774\ub294 \ub2e4\uc74c \uc21c\uc11c\ub85c \ucd94\uac00\ud569\ub2c8\ub2e4. \ub9e8 \ucc98\uc74c CloudStack \ub0b4\ubd80 \uad00\ub9ac \ud2b8\ub798\ud53d\uc744 \uc704\ud574\uc11c IP \uc8fc\uc18c \ubc94\uc704\ub97c \uc608\uc57d\ud569\ub2c8\ub2e4. IP \uc8fc\uc18c \ubc94\uc704\ub294 \ud074\ub77c\uc6b0\ub4dc \ub0b4\ubd80 \uac01 Zone\uc5d0\uc11c \uc911\ubcf5 \ud558\uc9c0 \uc54a\uac8c \uc608\uc57d\ud560 \ud544\uc694\uac00 \uc788\uc2b5\ub2c8\ub2e4. message.add.pod=Zone \uc5d0 \uc0c8\ub85c\uc6b4 Pod\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.primary.storage=Zone Pod \uc5d0 \uc0c8\ub85c\uc6b4 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.primary=\uc0c8\ub85c\uc6b4 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0\ub97c \ucd94\uac00\ud558\uae30 \uc704\ud574 \uc544\ub798 \ud30c\ub77c\ubbf8\ud130\ub97c \uc9c0\uc815\ud574 \uc8fc\uc2ed\uc2dc\uc624. @@ -1253,6 +1253,7 @@ message.delete.VPN.gateway=\ud604\uc7ac VPN \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c message.desc.advanced.zone=\ubcf4\ub2e4 \uc138\ub828\ub41c \ub124\ud2b8\uc6cc\ud06c \uae30\uc220\uc744 \uc9c0\uc6d0\ud569\ub2c8\ub2e4. \uc774 \ub124\ud2b8\uc6cc\ud06c \ubaa8\ub378\uc744 \uc120\ud0dd\ud558\uba74, \ubcf4\ub2e4 \uc720\uc5f0\ud558\uac8c \uac8c\uc2a4\ud2b8 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc815\ud558\uace0 \ubc29\ud654\ubcbd(fire wall), VPN, \ub124\ud2b8\uc6cc\ud06c \ub85c\ub4dc \uacf5\uc720 \uc7a5\uce58 \uae30\uc220 \uc9c0\uc6d0\uc640 \uac19\uc740 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \ud55c \ub124\ud2b8\uc6cc\ud06c \uc81c\uacf5\uc744 \uc81c\uacf5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. message.desc.basic.zone=\uac01 VM \uc778\uc2a4\ud134\uc2a4\uc5d0 IP \uc8fc\uc18c\uac00 \ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \uc9c1\uc811 \ud560\ub2f9\ud560 \uc218 \uc788\ub294 \ub2e8\uc77c \ub124\ud2b8\uc6cc\ud06c\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4. \ubcf4\uc548 \uadf8\ub8f9 (\uc804\uc1a1\uc6d0 IP \uc8fc\uc18c \ud544\ud130)\uacfc \uac19\uc740 \uce35 \uc138 \uac00\uc9c0 \ub808\ubca8 \ubc29\ubc95\uc73c\ub85c \uac8c\uc2a4\ud2b8\ub97c \ubd84\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. message.desc.cluster=\uac01 Pod\uc5d0\ub294 \ud55c \uac1c \uc774\uc0c1 \ud074\ub7ec\uc2a4\ud130\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \ucd5c\ucd08 \ud074\ub7ec\uc2a4\ud130\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \ud074\ub7ec\uc2a4\ud130\ub294 \ud638\uc2a4\ud2b8\ub97c \uadf8\ub8f9\ud654 \ud558\ub294 \ubc29\ubc95\uc785\ub2c8\ub2e4. \ud55c \ud074\ub7ec\uc2a4\ud130 \ub0b4\ubd80 \ud638\uc2a4\ud2b8\ub294 \ubaa8\ub450 \ub3d9\uc77c\ud55c \ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uad6c\uc131\ub418\uc5b4 \uac19\uc740 \ud558\uc774\ud37c \ubc14\uc774\uc800\ub97c \uc2e4\ud589\ud558\uace0 \uac19\uc740 \uc11c\ube0c \ub124\ud2b8\uc6cc\ud06c\uc0c1\uc5d0 \uc788\uc5b4 \uac19\uc740 \uacf5\uc720 \uc2a4\ud1a0\ub9ac\uc9c0\uc5d0 \uc811\uadfc \ud569\ub2c8\ub2e4. \uac01 \ud074\ub7ec\uc2a4\ud130\ub294 \ud55c \uac1c \uc774\uc0c1 \ud638\uc2a4\ud2b8\uc640 \ud55c \uac1c \uc774\uc0c1 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uc5d0\uc11c \uad6c\uc131\ub429\ub2c8\ub2e4. +message.desc.host=\uac01 \ud074\ub7ec\uc2a4\ud130\uc5d0\ub294 \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1 \uac8c\uc2a4\ud2b8 VM\ub97c \uc2e4\ud589\ud558\uae30 \uc704\ud55c \ud638\uc2a4\ud2b8 (\ucef4\ud4e8\ud130)\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 \ud638\uc2a4\ud2b8\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. CloudStack\uc73c\ub85c \ud638\uc2a4\ud2b8\ub97c \ub3d9\uc791\ud558\ub824\uba74 \ud638\uc2a4\ud2b8\uc5d0\uac8c \ud558\uc774\ud37c \ubc14\uc774\uc800\ub97c \uc124\uce58\ud558\uace0 IP \uc8fc\uc18c\ub97c \ud560\ub2f9\ud574 \ud638\uc2a4\ud2b8\uac00 CloudStack \uad00\ub9ac \uc11c\ubc84\uc5d0 \uc811\uc18d\ud558\ub3c4\ub85d \ud569\ub2c8\ub2e4.

    \ud638\uc2a4\ud2b8 DNS \uba85 \ub610\ub294 IP \uc8fc\uc18c, \uc0ac\uc6a9\uc790\uba85(\uc6d0\ub798 root)\uacfc \uc554\ud638 \ubc0f \ud638\uc2a4\ud2b8 \ubd84\ub958\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ub77c\ubca8\uc744 \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.desc.primary.storage=\uac01 \ud074\ub7ec\uc2a4\ud130\uc5d0\ub294 \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 \uc11c\ubc84\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0\ub294 \ud074\ub7ec\uc2a4\ud130 \ub0b4 \ubd80 \ud638\uc2a4\ud2b8\uc0c1\uc5d0\uc11c \ub3d9\uc791\ud558\ub294 \ubaa8\ub4e0 VM \ub514\uc2a4\ud06c \ubcfc\ub968\uc744 \ud3ec\ud568\ud569\ub2c8\ub2e4. \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ud37c \ubc14\uc774\uc800\uc5d0\uc11c \uae30\uc220 \uc9c0\uc6d0\ub418\ub294 \ud45c\uc900\uc5d0 \uc900\uac70\ud55c \ud504\ub85c\ud1a0\ucf5c\uc744 \uc0ac\uc6a9\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.desc.secondary.storage=\uac01 Zone\uc5d0\ub294 \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1\uc758 NFS \uc989 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 \uc11c\ubc84\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0\ub294 VM \ud15c\ud50c\ub9bf, ISO \uc774\ubbf8\uc9c0 \ubc0f VM \ub514\uc2a4\ud06c \ubcfc\ub968 \uc2a4\ub0c5\uc0f7\uc744 \ud3ec\ud568\ud569\ub2c8\ub2e4. \uc774 \uc11c\ubc84\ub294 Zone\ub0b4 \ubaa8\ub4e0 \ud638\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4.

    IP \uc8fc\uc18c\uc640 \ub0b4\ubcf4\ub0b4\ub0bc \uacbd\ub85c\ub97c \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.desc.zone=Zone\uc740 CloudStack \ud658\uacbd\ub0b4 \ucd5c\ub300 \uc870\uc9c1 \ub2e8\uc704\ub85c \uc6d0\ub798 \ub2e8\uc77c \ub370\uc774\ud130 \uc13c\ud130\uc5d0 \ud574\ub2f9\ud569\ub2c8\ub2e4. Zone\uc5d0 \ud574\uc11c \ubb3c\ub9ac\uc801\uc778 \ubd84\ub9ac\uc640 \uc911\ubcf5\uc131\uc774 \uc81c\uacf5\ub429\ub2c8\ub2e4. Zone\uc740 \ud55c \uac1c \uc774\uc0c1 Pod( \uac01 Pod\ub294 \ud638\uc2a4\ud2b8\uc640 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uc5d0\uc11c \uad6c\uc131)\uc640 Zone\ub0b4 \ubaa8\ub4e0 Pod\ub85c \uacf5\uc720\ub418\ub294 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\ub85c \uad6c\uc131\ub429\ub2c8\ub2e4. @@ -1380,6 +1381,7 @@ message.step.3.continue=\uc2e4\ud589\ud558\ub824\uba74 \ub514\uc2a4\ud06c\uc81c\ message.step.3.desc= message.step.4.continue=\uc2e4\ud589\ud558\ub824\uba74 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1 \uc120\ud0dd\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.step.4.desc=\uac00\uc0c1 \uc778\uc2a4\ud134\uc2a4\uac00 \uc811\uc18d\ud558\ub294 \uae30\ubcf8 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc120\ud0dd\ud574 \uc8fc\uc2ed\uc2dc\uc624. +message.storage.traffic=\ud638\uc2a4\ud2b8\ub098 CloudStack \uc2dc\uc2a4\ud15c VM \ub4f1 \uad00\ub9ac \uc11c\ubc84\uc640 \ud1b5\uc2e0\ud558\ub294 CloudStack \ub0b4\ubd80 \uc790\uc6d0\uac04 \ud2b8\ub798\ud53d\uc785\ub2c8\ub2e4. \uc5ec\uae30\uc11c \uc2a4\ud1a0\ub9ac\uc9c0 \ud2b8\ub798\ud53d\uc744 \uad6c\uc131\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.suspend.project=\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\ub97c \uc77c\uc2dc\uc815\uc9c0\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? message.template.desc=VM\uc758 \uc2dc\uc791\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 OS \uc774\ubbf8\uc9c0 message.tooltip.dns.1=Zone\ub0b4 VM \ub85c \uc0ac\uc6a9\ud558\ub294 DNS \uc11c\ubc84 \uc774\ub984\uc785\ub2c8\ub2e4. Zone \uacf5\uac1c IP \uc8fc\uc18c\uc5d0\uc11c \uc774 \uc11c\ubc84\uc5d0 \ud1b5\uc2e0\ud560 \uc218 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4. diff --git a/client/WEB-INF/classes/resources/messages_nb_NO.properties b/client/WEB-INF/classes/resources/messages_nb_NO.properties index 8fba48ca9c4..be412449398 100644 --- a/client/WEB-INF/classes/resources/messages_nb_NO.properties +++ b/client/WEB-INF/classes/resources/messages_nb_NO.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Endrede egenskaper error.could.not.enable.zone=Kunne ikke aktivere sonen error.installWizard.message=Noe gikk galt. G\u00e5 tilbake og korriger feilene. diff --git a/client/WEB-INF/classes/resources/messages_pt_BR.properties b/client/WEB-INF/classes/resources/messages_pt_BR.properties index 23123c16764..fd24f542e8d 100644 --- a/client/WEB-INF/classes/resources/messages_pt_BR.properties +++ b/client/WEB-INF/classes/resources/messages_pt_BR.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Alteradas propriedades do item confirm.enable.s3=Por favor preencha as informa\u00e7\u00f5es abaixo para habilitar suporte a storage secund\u00e1ria fornecida por S3 confirm.enable.swift=Por favor preencha as informa\u00e7\u00f5es abaixo para habilitar suporte ao Swift @@ -1113,6 +1112,7 @@ label.zones=Zonas label.zone.type=Tipo de Zona label.zone.wide=Zone-Wide label.zoneWizard.trafficType.guest=H\u00f3spede\: tr\u00e1fego entre m\u00e1quinas virtuais de usu\u00e1rios finais +label.zoneWizard.trafficType.management=Ger\u00eancia\: tr\u00e1fego entre recursos internos do CloudStack, incluindo quaisquer componentes que se comunicam com o servidor de gerenciamento, tais como hosts e m\u00e1quinas virtuais de sistema do CloudStack label.zoneWizard.trafficType.public=P\u00fablico\: tr\u00e1fego entre a internet e m\u00e1quinas virtuais na nuvem. label.zoneWizard.trafficType.storage=Storage\: tr\u00e1fego entre servidores de storage prim\u00e1ria e secund\u00e1ria, tais como templates de m\u00e1quinas virtuais e snapshots label.zone=Zona diff --git a/client/WEB-INF/classes/resources/messages_ru_RU.properties b/client/WEB-INF/classes/resources/messages_ru_RU.properties index 5818abc9199..b28f6b69e6f 100644 --- a/client/WEB-INF/classes/resources/messages_ru_RU.properties +++ b/client/WEB-INF/classes/resources/messages_ru_RU.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b confirm.enable.swift=\u0417\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438 Swift error.could.not.enable.zone=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u043e\u043d\u0443 @@ -1131,6 +1130,7 @@ message.additional.networks.desc=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u044 message.add.load.balancer=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 \u0437\u043e\u043d\u0443 message.add.load.balancer.under.ip=\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0432 IP\: message.add.network=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0441\u0435\u0442\u044c \u0434\u043b\u044f \u0437\u043e\u043d\u044b\: +message.add.pod.during.zone.creation=\u041a\u0430\u0436\u0434\u0430\u044f \u0437\u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0435\u043d\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435 \u043f\u0435\u0440\u0432\u044b\u043c. \u0421\u0442\u0435\u043d\u0434 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0443\u0437\u043b\u044b \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u0448\u0430\u0433\u0435. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 IP \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0441\u0435\u0442\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 IP \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0437\u043e\u043d\u044b \u043e\u0431\u043b\u0430\u043a\u0430. message.add.pod=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0434\u043b\u044f \u0437\u043e\u043d\u044b message.add.primary.storage=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u0437\u043e\u043d\u044b , \u0441\u0442\u0435\u043d\u0434\u0430 message.add.primary=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 @@ -1185,6 +1185,7 @@ message.delete.user=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442 message.desc.advanced.zone=\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u0442\u043e\u043f\u043e\u043b\u043e\u0433\u0438\u0439. \u042d\u0442\u0430 \u0441\u0435\u0442\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0433\u043e\u0441\u0442\u0435\u0432\u043e\u0439 \u0441\u0435\u0442\u0438 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0441\u043b\u0443\u0433, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u044d\u043a\u0440\u0430\u043d, VPN, \u0438\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. message.desc.basic.zone=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0434\u0438\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u0412\u041c \u0438\u043c\u0435\u0435\u0442 \u00ab\u0431\u0435\u043b\u044b\u0439\u00bb IP-\u0430\u0434\u0440\u0435\u0441 \u0441\u0435\u0442\u0438. \u0418\u0437\u043e\u043b\u044f\u0446\u0438\u0438 \u0433\u043e\u0441\u0442\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0435\u0442\u0438 3-\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0433\u0440\u0443\u043f\u043f\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 (\u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f IP-\u0432\u0434\u0440\u0435\u0441\u043e\u0432) message.desc.cluster=\u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u043e\u0432, \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435. \u041a\u043b\u0430\u0441\u0442\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u0443 \u0443\u0437\u043b\u043e\u0432. \u0423\u0437\u043b\u044b \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u0438\u043d \u0433\u0438\u043f\u0435\u0440\u0432\u0438\u0437\u043e\u0440, \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0438 \u0438\u043c\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438 \u0442\u043e\u043c\u0443 \u0436\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443. \u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0443\u0437\u043b\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449. +message.desc.host=\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u0438\u043d \u0443\u0437\u0435\u043b (\u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440) \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0412\u041c, \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u0437 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0432\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435 \u0441\u0435\u0439\u0447\u0430\u0441. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0443\u0437\u043b\u0430 \u0432 CloudStack \u0432\u0430\u0436\u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0433\u0438\u043f\u0435\u0440\u0432\u0438\u0437\u043e\u0440\u0430 \u043d\u0430 \u0443\u0437\u0435\u043b, \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 IP \u043a \u0443\u0437\u043b\u0443 \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0443\u0437\u043b\u0430 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f CloudStack.

    \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0438\u043c\u044f DNS \u0438\u043b\u0438 \u0430\u0434\u0440\u0435\u0441 IP, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043a \u041e\u0421 (\u043e\u0431\u044b\u0447\u043d\u043e root), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432. message.desc.primary.storage=\u041a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u0435\u0439\u0447\u0430\u0441. \u041f\u0435\u0440\u0432\u0438\u0447\u043d\u0430\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044b \u0436\u0435\u0441\u0442\u043a\u043e\u0433\u043e \u0434\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u043d\u0430 \u0443\u0437\u043b\u0430\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0433\u0438\u043f\u0435\u0440\u0432\u0438\u0437\u043e\u0440\u0430. message.desc.secondary.storage=\u041a\u0430\u0436\u0434\u0430\u044f \u0437\u043e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c NFS \u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438 \u0438\u0445 \u043d\u0430\u0434\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0412\u041c, \u043e\u0431\u0440\u0430\u0437\u043e\u0432 ISO \u0438 \u0441\u043d\u0438\u043c\u043a\u043e\u0432 \u0412\u041c. \u042d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432 \u0437\u043e\u043d\u044b.

    \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u0443\u0442\u044c. message.desc.zone=layer 3 @@ -1309,6 +1310,7 @@ message.step.3.continue=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\ message.step.3.desc= message.step.4.continue=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0441\u0435\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f. message.step.4.desc=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0441\u0435\u0442\u044c, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0430. +message.storage.traffic=\u0422\u0440\u0430\u0444\u0438\u043a \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 CloudStack, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0441\u0442\u044b \u0438 CloudStack \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0442\u0440\u0430\u0444\u0438\u043a \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u0434\u0435\u0441\u044c. message.suspend.project=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442? message.template.desc=\u041e\u0431\u0440\u0430\u0437 \u041e\u0421, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0439 \u0432 \u0412\u041c message.tooltip.dns.1=\u0418\u043c\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 DNS \u0434\u043b\u044f \u0412\u041c \u044d\u0442\u043e\u0439 \u0437\u043e\u043d\u044b. \u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u0442\u043e\u0439 \u0437\u043e\u043d\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. diff --git a/client/WEB-INF/classes/resources/messages_zh_CN.properties b/client/WEB-INF/classes/resources/messages_zh_CN.properties index 687ef60b3c1..30daacc3627 100644 --- a/client/WEB-INF/classes/resources/messages_zh_CN.properties +++ b/client/WEB-INF/classes/resources/messages_zh_CN.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\u66f4\u6539\u9879\u76ee\u5c5e\u6027 confirm.enable.s3=\u8bf7\u586b\u5199\u4e0b\u5217\u4fe1\u606f\u4ee5\u542f\u7528\u652f\u6301S3\u7684\u4e8c\u7ea7\u5b58\u50a8 confirm.enable.swift=\u8bf7\u586b\u5199\u4ee5\u4e0b\u4fe1\u606f\u4ee5\u542f\u7528\u5bf9 SWIFT \u7684\u652f\u6301 @@ -622,12 +621,17 @@ label.keyboard.type=\u952e\u76d8\u7c7b\u578b label.key=\u5bc6\u94a5 label.kvm.traffic.label=KVM \u6d41\u91cf\u6807\u7b7e label.label=\u6807\u7b7e +label.lang.arabic=\u963f\u62c9\u4f2f\u8bed label.lang.brportugese=\u5df4\u897f\u8461\u8404\u7259\u8bed +label.lang.catalan=\u52a0\u6cf0\u7f57\u5c3c\u4e9a\u8bed label.lang.chinese=\u7b80\u4f53\u4e2d\u6587 label.lang.english=\u82f1\u8bed label.lang.french=\u6cd5\u8bed +label.lang.german=\u5fb7\u8bed +label.lang.italian=\u610f\u5927\u5229\u8bed label.lang.japanese=\u65e5\u8bed label.lang.korean=\u97e9\u56fd\u8bed +label.lang.norwegian=\u632a\u5a01\u8bed label.lang.russian=\u4fc4\u8bed label.lang.spanish=\u897f\u73ed\u7259\u8bed label.last.disconnected=\u4e0a\u6b21\u65ad\u5f00\u8fde\u63a5\u65f6\u95f4 @@ -1165,6 +1169,7 @@ label.zone.type=\u533a\u57df\u7c7b\u578b label.zone=\u533a\u57df label.zone.wide=\u6574\u4e2a\u533a\u57df label.zoneWizard.trafficType.guest=\u6765\u5bbe\u7f51\u7edc\: \u5ba2\u6237\u865a\u62df\u673a\u4e4b\u95f4\u7684\u7f51\u7edc\u6d41\u91cf +label.zoneWizard.trafficType.management=\u7ba1\u7406\u7f51\: CloudStack\u5185\u90e8\u8d44\u6e90\u4e4b\u95f4\u7684\u7f51\u7edc\u6d41\u91cf, \u5305\u62ec\u4e0e\u7ba1\u7406\u670d\u52a1\u5668\u4ea4\u4e92\u7684\u4efb\u4f55\u7ec4\u4ef6, \u6bd4\u5982\u4e3b\u673a\u548cCloudStack\u7cfb\u7edf\u865a\u62df\u673a label.zoneWizard.trafficType.public=\u516c\u5171\u7f51\u7edc\: \u4e91\u73af\u5883\u4e2d\u865a\u62df\u673a\u4e0e\u56e0\u7279\u7f51\u4e4b\u95f4\u7684\u7f51\u7edc\u6d41\u91cf. label.zoneWizard.trafficType.storage=\u5b58\u50a8\u7f51\: \u4e3b\u5b58\u50a8\u4e0e\u4e8c\u7ea7\u5b58\u50a8\u670d\u52a1\u5668\u4e4b\u95f4\u7684\u6d41\u91cf, \u6bd4\u5982\u865a\u673a\u6a21\u677f\u548c\u5feb\u7167 managed.state=\u6258\u7ba1\u72b6\u6001 @@ -1255,6 +1260,7 @@ message.add.load.balancer=\u5411\u533a\u57df\u4e2d\u6dfb\u52a0\u4e00\u4e2a\u8d1f message.add.load.balancer.under.ip=\u5df2\u5728\u4ee5\u4e0b IP \u4e0b\u6dfb\u52a0\u8d1f\u8f7d\u5e73\u8861\u5668\u89c4\u5219\: message.add.network=\u4e3a\u533a\u57df\u6dfb\u52a0\u4e00\u4e2a\u65b0\u7f51\u7edc\: message.add.new.gateway.to.vpc=\u8bf7\u6307\u5b9a\u5c06\u65b0\u7f51\u5173\u6dfb\u52a0\u5230\u6b64 VPC \u6240\u9700\u7684\u4fe1\u606f\u3002 +message.add.pod.during.zone.creation=\u6bcf\u4e2a\u533a\u57df\u4e2d\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u63d0\u4f9b\u70b9\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u63d0\u4f9b\u70b9\u3002\u63d0\u4f9b\u70b9\u4e2d\u5305\u542b\u4e3b\u673a\u548c\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\uff0c\u60a8\u5c06\u5728\u968f\u540e\u7684\u67d0\u4e2a\u6b65\u9aa4\u4e2d\u6dfb\u52a0\u8fd9\u4e9b\u4e3b\u673a\u548c\u670d\u52a1\u5668\u3002\u9996\u5148\uff0c\u8bf7\u4e3a CloudStack \u7684\u5185\u90e8\u7ba1\u7406\u6d41\u91cf\u914d\u7f6e\u4e00\u4e2a\u9884\u7559 IP \u5730\u5740\u8303\u56f4\u3002\u9884\u7559\u7684 IP \u8303\u56f4\u5bf9\u4e91\u4e2d\u7684\u6bcf\u4e2a\u533a\u57df\u6765\u8bf4\u5fc5\u987b\u552f\u4e00\u3002 message.add.pod=\u4e3a\u533a\u57df \u6dfb\u52a0\u4e00\u4e2a\u65b0\u63d0\u4f9b\u70b9 message.add.primary.storage=\u4e3a\u533a\u57df \u3001\u63d0\u4f9b\u70b9 \u6dfb\u52a0\u4e00\u4e2a\u65b0\u7684\u4e3b\u5b58\u50a8 message.add.primary=\u8bf7\u6307\u5b9a\u4ee5\u4e0b\u53c2\u6570\u4ee5\u6dfb\u52a0\u4e00\u4e2a\u65b0\u4e3b\u5b58\u50a8 @@ -1316,6 +1322,7 @@ message.delete.VPN.gateway=\u8bf7\u786e\u8ba4\u60a8\u786e\u5b9e\u8981\u5220\u966 message.desc.advanced.zone=\u9002\u7528\u4e8e\u66f4\u52a0\u590d\u6742\u7684\u7f51\u7edc\u62d3\u6251\u3002\u6b64\u7f51\u7edc\u6a21\u5f0f\u5728\u5b9a\u4e49\u6765\u5bbe\u7f51\u7edc\u5e76\u63d0\u4f9b\u9632\u706b\u5899\u3001VPN \u6216\u8d1f\u8f7d\u5e73\u8861\u5668\u652f\u6301\u7b49\u81ea\u5b9a\u4e49\u7f51\u7edc\u65b9\u6848\u65b9\u9762\u63d0\u4f9b\u4e86\u6700\u5927\u7684\u7075\u6d3b\u6027\u3002 message.desc.basic.zone=\u63d0\u4f9b\u4e00\u4e2a\u7f51\u7edc\uff0c\u5c06\u76f4\u63a5\u4ece\u6b64\u7f51\u7edc\u4e2d\u4e3a\u6bcf\u4e2a VM \u5b9e\u4f8b\u5206\u914d\u4e00\u4e2a IP\u3002\u53ef\u4ee5\u901a\u8fc7\u5b89\u5168\u7ec4\u7b49\u7b2c 3 \u5c42\u65b9\u5f0f\u63d0\u4f9b\u6765\u5bbe\u9694\u79bb(IP \u5730\u5740\u6e90\u8fc7\u6ee4)\u3002 message.desc.cluster=\u6bcf\u4e2a\u63d0\u4f9b\u70b9\u4e2d\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u7fa4\u96c6\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u7fa4\u96c6\u3002\u7fa4\u96c6\u63d0\u4f9b\u4e86\u4e00\u79cd\u7f16\u7ec4\u4e3b\u673a\u7684\u65b9\u6cd5\u3002\u7fa4\u96c6\u4e2d\u7684\u6240\u6709\u4e3b\u673a\u90fd\u5177\u6709\u76f8\u540c\u7684\u786c\u4ef6\uff0c\u8fd0\u884c\u76f8\u540c\u7684\u865a\u62df\u673a\u7ba1\u7406\u7a0b\u5e8f\uff0c\u4f4d\u4e8e\u76f8\u540c\u7684\u5b50\u7f51\u4e2d\uff0c\u5e76\u8bbf\u95ee\u76f8\u540c\u7684\u5171\u4eab\u5b58\u50a8\u3002\u6bcf\u4e2a\u7fa4\u96c6\u7531\u4e00\u4e2a\u6216\u591a\u4e2a\u4e3b\u673a\u4ee5\u53ca\u4e00\u4e2a\u6216\u591a\u4e2a\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\u7ec4\u6210\u3002 +message.desc.host=\u6bcf\u4e2a\u7fa4\u96c6\u4e2d\u5fc5\u987b\u81f3\u5c11\u5305\u542b\u4e00\u4e2a\u4e3b\u673a\u4ee5\u4f9b\u6765\u5bbe VM \u5728\u4e0a\u9762\u8fd0\u884c\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u4e3b\u673a\u3002\u8981\u4f7f\u4e3b\u673a\u5728 CloudStack \u4e2d\u8fd0\u884c\uff0c\u5fc5\u987b\u5728\u6b64\u4e3b\u673a\u4e0a\u5b89\u88c5\u865a\u62df\u673a\u7ba1\u7406\u7a0b\u5e8f\u8f6f\u4ef6\uff0c\u4e3a\u5176\u5206\u914d\u4e00\u4e2a IP \u5730\u5740\uff0c\u5e76\u786e\u4fdd\u5c06\u5176\u8fde\u63a5\u5230 CloudStack \u7ba1\u7406\u670d\u52a1\u5668\u3002

    \u8bf7\u63d0\u4f9b\u4e3b\u673a\u7684 DNS \u6216 IP \u5730\u5740\u3001\u7528\u6237\u540d(\u901a\u5e38\u4e3a root)\u548c\u5bc6\u7801\uff0c\u4ee5\u53ca\u7528\u4e8e\u5bf9\u4e3b\u673a\u8fdb\u884c\u5206\u7c7b\u7684\u4efb\u4f55\u6807\u7b7e\u3002 message.desc.primary.storage=\u6bcf\u4e2a\u7fa4\u96c6\u4e2d\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\u3002\u4e3b\u5b58\u50a8\u4e2d\u5305\u542b\u5728\u7fa4\u96c6\u4e2d\u7684\u4e3b\u673a\u4e0a\u8fd0\u884c\u7684\u6240\u6709 VM \u7684\u78c1\u76d8\u5377\u3002\u8bf7\u4f7f\u7528\u5e95\u5c42\u865a\u62df\u673a\u7ba1\u7406\u7a0b\u5e8f\u652f\u6301\u7684\u7b26\u5408\u6807\u51c6\u7684\u534f\u8bae\u3002 message.desc.secondary.storage=\u6bcf\u4e2a\u533a\u57df\u4e2d\u5fc5\u987b\u81f3\u5c11\u5305\u542b\u4e00\u4e2a NFS \u6216\u8f85\u52a9\u5b58\u50a8\u670d\u52a1\u5668\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a NFS \u6216\u8f85\u52a9\u5b58\u50a8\u670d\u52a1\u5668\u3002\u8f85\u52a9\u5b58\u50a8\u7528\u4e8e\u5b58\u50a8 VM \u6a21\u677f\u3001ISO \u6620\u50cf\u548c VM \u78c1\u76d8\u5377\u5feb\u7167\u3002\u6b64\u670d\u52a1\u5668\u5fc5\u987b\u5bf9\u533a\u57df\u4e2d\u7684\u6240\u6709\u670d\u52a1\u5668\u53ef\u7528\u3002

    \u8bf7\u63d0\u4f9b IP \u5730\u5740\u548c\u5bfc\u51fa\u8def\u5f84\u3002 message.desc.zone=\u533a\u57df\u662f CloudStack \u4e2d\u6700\u5927\u7684\u7ec4\u7ec7\u5355\u4f4d\uff0c\u4e00\u4e2a\u533a\u57df\u901a\u5e38\u4e0e\u4e00\u4e2a\u6570\u636e\u4e2d\u5fc3\u76f8\u5bf9\u5e94\u3002\u533a\u57df\u53ef\u63d0\u4f9b\u7269\u7406\u9694\u79bb\u548c\u5197\u4f59\u3002\u4e00\u4e2a\u533a\u57df\u7531\u4e00\u4e2a\u6216\u591a\u4e2a\u63d0\u4f9b\u70b9\u4ee5\u53ca\u7531\u533a\u57df\u4e2d\u7684\u6240\u6709\u63d0\u4f9b\u70b9\u5171\u4eab\u7684\u4e00\u4e2a\u8f85\u52a9\u5b58\u50a8\u670d\u52a1\u5668\u7ec4\u6210\uff0c\u5176\u4e2d\u6bcf\u4e2a\u63d0\u4f9b\u70b9\u4e2d\u5305\u542b\u591a\u4e2a\u4e3b\u673a\u548c\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\u3002 @@ -1445,6 +1452,7 @@ message.step.3.continue=\u8bf7\u9009\u62e9\u4e00\u79cd\u78c1\u76d8\u65b9\u6848\u message.step.3.desc= message.step.4.continue=\u8bf7\u81f3\u5c11\u9009\u62e9\u4e00\u4e2a\u7f51\u7edc\u4ee5\u7ee7\u7eed message.step.4.desc=\u8bf7\u9009\u62e9\u865a\u62df\u5b9e\u4f8b\u8981\u8fde\u63a5\u5230\u7684\u4e3b\u7f51\u7edc\u3002 +message.storage.traffic=CloudStack \u5185\u90e8\u8d44\u6e90(\u5305\u62ec\u4e0e\u7ba1\u7406\u670d\u52a1\u5668\u901a\u4fe1\u7684\u4efb\u4f55\u7ec4\u4ef6\uff0c\u4f8b\u5982\u4e3b\u673a\u548c CloudStack \u7cfb\u7edf VM)\u4e4b\u95f4\u7684\u6d41\u91cf\u3002\u8bf7\u5728\u6b64\u5904\u914d\u7f6e\u5b58\u50a8\u6d41\u91cf\u3002 message.suspend.project=\u662f\u5426\u786e\u5b9e\u8981\u6682\u505c\u6b64\u9879\u76ee? message.template.desc=\u53ef\u7528\u4e8e\u542f\u52a8 VM \u7684\u64cd\u4f5c\u7cfb\u7edf\u6620\u50cf message.tooltip.dns.1=\u4f9b\u533a\u57df\u4e2d\u7684 VM \u4f7f\u7528\u7684 DNS \u670d\u52a1\u5668\u540d\u79f0\u3002\u533a\u57df\u7684\u516c\u7528 IP \u5730\u5740\u5fc5\u987b\u8def\u7531\u5230\u6b64\u670d\u52a1\u5668\u3002 From 82974458a675c52e888c91f569f0f1ca278197d7 Mon Sep 17 00:00:00 2001 From: Harikrishna Patnala Date: Mon, 27 May 2013 18:24:35 +0530 Subject: [PATCH 163/201] CLOUDSTACK-2672: Adding isVolatile parameter in service offering response object Signed off by :- Nitin Mehta --- .../api/response/ServiceOfferingResponse.java | 11 +++++++++++ .../api/query/dao/ServiceOfferingJoinDaoImpl.java | 1 + .../com/cloud/api/query/vo/ServiceOfferingJoinVO.java | 11 +++++++++++ setup/db/db/schema-410to420.sql | 1 + 4 files changed, 24 insertions(+) diff --git a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java index 08ebbb05887..31533f87728 100644 --- a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java @@ -60,6 +60,9 @@ public class ServiceOfferingResponse extends BaseResponse { @SerializedName("limitcpuuse") @Param(description="restrict the CPU usage to committed service offering") private Boolean limitCpuUse; + @SerializedName("isvolatile") @Param(description="true if the vm needs to be volatile, i.e., on every reboot of vm from API root disk is discarded and creates a new root disk") + private Boolean isVolatile; + @SerializedName("tags") @Param(description="the tags for the service offering") private String tags; @@ -237,4 +240,12 @@ public class ServiceOfferingResponse extends BaseResponse { public void setDeploymentPlanner(String deploymentPlanner) { this.deploymentPlanner = deploymentPlanner; } + + public boolean getVolatileVm() { + return isVolatile; + } + + public void setVolatileVm(boolean isVolatile) { + this.isVolatile = isVolatile; + } } diff --git a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java index ce20562d5f7..56e4d0a369e 100644 --- a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java @@ -68,6 +68,7 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase Date: Sat, 25 May 2013 17:46:13 +0530 Subject: [PATCH 164/201] generate an action event when portable IP association is transferred from a network to different network --- api/src/com/cloud/event/EventTypes.java | 1 + server/src/com/cloud/network/NetworkManagerImpl.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index da96294c14c..6dfb1ab57b6 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -436,6 +436,7 @@ public class EventTypes { public static final String EVENT_PORTABLE_IP_RANGE_CREATE = "PORTABLE.IP.RANGE.CREATE"; public static final String EVENT_PORTABLE_IP_RANGE_DELETE = "PORTABLE.IP.RANGE.DELETE"; + public static final String EVENT_PORTABLE_IP_TRANSFER = "PORTABLE.IP.TRANSFER"; static { diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 254510b15a9..d699b2e02e2 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -39,6 +39,7 @@ import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.domain.Domain; import com.cloud.domain.dao.DomainDao; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.UsageEventDao; @@ -1063,6 +1064,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L _ipAddressDao.update(ipAddrId, ip); txn.commit(); + ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, + EventTypes.EVENT_PORTABLE_IP_TRANSFER, "Portable IP associated is transferred from network " + + currentNetworkId + " to " + newNetworkId); } @Override From 883333c2143e9f3b14a3bc91f8e486e3574dfa37 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Mon, 27 May 2013 18:42:33 +0530 Subject: [PATCH 165/201] CLOUDSTACK-2700:on network/vpc delete, portable IP should be still associated with account Unlike public ip which gets dis-associated (released) with the account on network/VPC delete, portable IP should continue to be associated with the account even when the network/VPC with which it is currently associated in deleted. This fix ensures portable IP are associated to account even after network/vpc is deleted. --- api/src/com/cloud/network/NetworkService.java | 2 +- .../src/com/cloud/network/NetworkManager.java | 9 +++++---- .../com/cloud/network/NetworkManagerImpl.java | 20 ++++++++++++++----- .../com/cloud/network/NetworkServiceImpl.java | 10 +++++++--- .../cloud/network/rules/RulesManagerImpl.java | 12 +++++------ .../com/cloud/network/vpc/VpcManagerImpl.java | 15 +++++++++++--- .../com/cloud/user/AccountManagerImpl.java | 8 ++++++++ .../cloud/network/MockNetworkManagerImpl.java | 2 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 2 +- 9 files changed, 56 insertions(+), 24 deletions(-) diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 59702a2864e..405cecd8847 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -55,7 +55,7 @@ public interface NetworkService { IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException; - boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; + boolean releasePortableIpAddress(long ipAddressId); Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 05bc26ee5c2..19f396abe6e 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -268,6 +268,11 @@ public interface NetworkManager { IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; + IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) + throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; + + boolean releasePortableIpAddress(long addrId); + IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; @@ -362,10 +367,6 @@ public interface NetworkManager { IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; - - IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) - throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; - Map finalizeServicesAndProvidersForNetwork(NetworkOffering offering, Long physicalNetworkId); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index d699b2e02e2..b443dca6abc 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1118,7 +1118,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @DB - private void releasePortableIpAddress(long addrId) { + @Override + public boolean releasePortableIpAddress(long addrId) { Transaction txn = Transaction.currentTxn(); GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange"); @@ -1133,12 +1134,13 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // removed the provisioned vlan VlanVO vlan = _vlanDao.findById(ip.getVlanId()); - _vlanDao.expunge(vlan.getId()); + _vlanDao.remove(vlan.getId()); // remove the provisioned public ip address - _ipAddressDao.expunge(ip.getId()); + _ipAddressDao.remove(ip.getId()); txn.commit(); + return true; } finally { portableIpLock.releaseRef(); } @@ -3537,8 +3539,16 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L List ipsToRelease = _ipAddressDao.listByAssociatedNetwork(networkId, null); for (IPAddressVO ipToRelease : ipsToRelease) { if (ipToRelease.getVpcId() == null) { - IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId()); - assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable."; + if (!ipToRelease.isPortable()) { + IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId()); + assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable."; + } else { + // portable IP address are associated with owner, until explicitly requested to be disassociated + // so as part of network clean up just break IP association with guest network + ipToRelease.setAssociatedWithNetworkId(null); + _ipAddressDao.update(ipToRelease.getId(), ipToRelease); + s_logger.debug("Portable IP address " + ipToRelease + " is no longer associated with any network"); + } } else { _vpcMgr.unassignIPFromVpcNetwork(ipToRelease.getId(), network.getId()); } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 1533ca9bc4f..f880bccb046 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -591,8 +591,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Override @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RELEASE, eventDescription = "disassociating portable Ip", async = true) - public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { - return releaseIpAddressInternal(ipAddressId); + public boolean releasePortableIpAddress(long ipAddressId) { + try { + return releaseIpAddressInternal(ipAddressId); + } catch (Exception e) { + return false; + } } @Override @@ -880,7 +884,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { boolean success = _networkMgr.disassociatePublicIpAddress(ipAddressId, userId, caller); if (success) { - if (!ipVO.isPortable()) { + if (ipVO.isPortable()) { return success; } Long networkId = ipVO.getAssociatedWithNetworkId(); diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 883455377f4..3c95cef440f 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -490,10 +490,9 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules "a part of enable static nat"); return false; } - performedIpAssoc = true; } else if (ipAddress.isPortable()) { - s_logger.info("Portable IP " + ipAddress.getUuid() + " is not associated with the network, so" + - "associate IP with the network " + networkId); + s_logger.info("Portable IP " + ipAddress.getUuid() + " is not associated with the network yet " + + " so associate IP with the network " + networkId); try { // check if StaticNat service is enabled in the network _networkModel.checkIpForService(ipAddress, Service.StaticNat, networkId); @@ -504,13 +503,12 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules } // associate portable IP with guest network - _networkMgr.associatePortableIPToGuestNetwork(ipId, networkId, false); + ipAddress = _networkMgr.associatePortableIPToGuestNetwork(ipId, networkId, false); } catch (Exception e) { s_logger.warn("Failed to associate portable id=" + ipId + " to network id=" + networkId + " as " + "a part of enable static nat"); return false; } - performedIpAssoc = true; } } else if (ipAddress.getAssociatedWithNetworkId() != networkId) { if (ipAddress.isPortable()) { @@ -520,14 +518,16 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules // check if portable IP can be transferred across the networks if (_networkMgr.isPortableIpTransferableFromNetwork(ipId, ipAddress.getAssociatedWithNetworkId() )) { try { + // transfer the portable IP and refresh IP details _networkMgr.transferPortableIP(ipId, ipAddress.getAssociatedWithNetworkId(), networkId); + ipAddress = _ipAddressDao.findById(ipId); } catch (Exception e) { s_logger.warn("Failed to associate portable id=" + ipId + " to network id=" + networkId + " as " + "a part of enable static nat"); return false; } } else { - throw new InvalidParameterValueException("Portable IP: " + ipId + " has associated services" + + throw new InvalidParameterValueException("Portable IP: " + ipId + " has associated services " + "in network " + ipAddress.getAssociatedWithNetworkId() + " so can not be transferred to " + " network " + networkId); } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 1aab7320fb4..15e1539ae7d 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -1217,9 +1217,18 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis List ipsToRelease = _ipAddressDao.listByAssociatedVpc(vpcId, null); s_logger.debug("Releasing ips for vpc id=" + vpcId + " as a part of vpc cleanup"); for (IPAddressVO ipToRelease : ipsToRelease) { - success = success && _ntwkMgr.disassociatePublicIpAddress(ipToRelease.getId(), callerUserId, caller); - if (!success) { - s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup"); + if (ipToRelease.isPortable()) { + // portable IP address are associated with owner, until explicitly requested to be disassociated. + // so as part of VPC clean up just break IP association with VPC + ipToRelease.setVpcId(null); + ipToRelease.setAssociatedWithNetworkId(null); + _ipAddressDao.update(ipToRelease.getId(), ipToRelease); + s_logger.debug("Portable IP address " + ipToRelease + " is no longer associated with any VPC"); + } else { + success = success && _ntwkMgr.disassociatePublicIpAddress(ipToRelease.getId(), callerUserId, caller); + if (!success) { + s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup"); + } } } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 7421422d294..e72005e8214 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -731,6 +731,14 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M _resourceCountDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account); _resourceLimitDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account); + // release account specific acquired portable IP's. Since all the portable IP's must have been already + // disassociated with VPC/guest network (due to deletion), so just mark portable IP as free. + List portableIpsToRelease = _ipAddressDao.listByAccount(accountId); + for (IpAddress ip : portableIpsToRelease) { + s_logger.debug("Releasing portable ip " + ip + " as a part of account id=" + accountId + " cleanup"); + _networkMgr.releasePortableIpAddress(ip.getId()); + } + return true; } catch (Exception ex) { s_logger.warn("Failed to cleanup account " + account + " due to ", ex); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index e5d34fbacc7..53c0fa82672 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -887,7 +887,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } @Override - public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + public boolean releasePortableIpAddress(long ipAddressId) { return false;// TODO Auto-generated method stub } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 7129273a50c..a1ece441863 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -210,7 +210,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } @Override - public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + public boolean releasePortableIpAddress(long ipAddressId) { return false;// TODO Auto-generated method stub } From e9a6d47316d8de90eb662e9938ea7fcbe0ee0596 Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Tue, 28 May 2013 11:55:21 +0900 Subject: [PATCH 166/201] agent: fix network.bridge.type to be optional New network.bridge.type was introduced, but for buckward compatibility, the key should be optional. Signed-off-by: Hiroaki KAWAI --- agent/bindir/cloud-setup-agent.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in index d6f481db2e0..6932672b962 100755 --- a/agent/bindir/cloud-setup-agent.in +++ b/agent/bindir/cloud-setup-agent.in @@ -96,7 +96,9 @@ if __name__ == '__main__': parser.add_option("--guestNic", dest="guestNic", help="Guest traffic interface") old_config = configFileOps("@AGENTSYSCONFDIR@/agent.properties") - glbEnv.bridgeType = old_config.getEntry("network.bridge.type").lower() + bridgeType = old_config.getEntry("network.bridge.type").lower() + if bridgeType: + glbEnv.bridgeType = bridgeType (options, args) = parser.parse_args() if options.auto is None: From 204bdac77f2c48e304b8bd7ccf2c85a69f4885ef Mon Sep 17 00:00:00 2001 From: ashutoshkelkar Date: Thu, 23 May 2013 11:23:34 +0530 Subject: [PATCH 167/201] Fix for repeated log lines in test case logs. Signed-off-by: Prasanna Santhanam --- 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 57438688486..4b64aaee835 100644 --- a/tools/marvin/marvin/TestCaseExecuteEngine.py +++ b/tools/marvin/marvin/TestCaseExecuteEngine.py @@ -72,7 +72,7 @@ class TestCaseExecuteEngine(object): self.injectTestCase(test) else: #logger bears the name of the test class - testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) + testcaselogger = logging.getLogger("%s" % (test)) fh = logging.FileHandler(self.logfile) fh.setFormatter(self.logformat) testcaselogger.addHandler(fh) From 8fd476e2fddd75949362630823d1a574d44a1705 Mon Sep 17 00:00:00 2001 From: SrikanteswaraRao Talluri Date: Fri, 17 May 2013 14:42:26 +0530 Subject: [PATCH 168/201] CLOUDSTACK-2557: Fix add primary storage tests Signed-off-by: Prasanna Santhanam --- .../integration/smoke/test_primary_storage.py | 134 ++++++++++-------- 1 file changed, 73 insertions(+), 61 deletions(-) diff --git a/test/integration/smoke/test_primary_storage.py b/test/integration/smoke/test_primary_storage.py index eb747fa6588..598654da112 100644 --- a/test/integration/smoke/test_primary_storage.py +++ b/test/integration/smoke/test_primary_storage.py @@ -35,32 +35,17 @@ class Services: def __init__(self): self.services = { - "nfs": { - 0: { - "url": "nfs://192.168.100.131/testprimary", + "nfs": + { + "url": "nfs://10.147.28.7/export/home/talluri/testprimary", # Format: File_System_Type/Location/Path - "name": "Primary XEN", - "hypervisor": 'XEN', + "name": "Primary XEN" }, - 1: { - "url": "nfs://192.168.100.131/Primary", - "name": "Primary KVM", - "hypervisor": 'KVM', - }, - 2: { - "url": "nfs://192.168.100.131/Primary", - "name": "Primary VMWare", - "hypervisor": 'VMWare', - }, - }, "iscsi": { - 0: { "url": "iscsi://192.168.100.21/iqn.2012-01.localdomain.clo-cstack-cos6:iser/1", # Format : iscsi://IP Address/IQN number/LUN# - "name": "Primary iSCSI", - "hypervisor": 'XEN', - }, - }, + "name": "Primary iSCSI" + } } class TestPrimaryStorageServices(cloudstackTestCase): @@ -85,31 +70,27 @@ class TestPrimaryStorageServices(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @unittest.skip("skipped - will not be adding storage in our environments") - def test_01_primary_storage(self): + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + def test_01_primary_storage_nfs(self): """Test primary storage pools - XEN, KVM, VMWare """ # Validate the following: - # 1. verify hypervisortype returned by api is Xen/KVM/VMWare + # 1. List Clusters # 2. verify that the cluster is in 'Enabled' allocation state # 3. verify that the host is added successfully and # in Up state with listHosts api response #Create NFS storage pools with on XEN/KVM/VMWare clusters - for k, v in self.services["nfs"].items(): - clusters = list_clusters( - self.apiclient, - zoneid=self.zone.id, - hypervisortype=v["hypervisor"] - ) - self.assertEqual( - isinstance(clusters, list), - True, - "Check list response returns a valid list" - ) - cluster = clusters[0] + + clusters = list_clusters( + self.apiclient, + zoneid=self.zone.id + ) + assert isinstance(clusters,list) and len(clusters)>0 + for cluster in clusters: + #Host should be present before adding primary storage list_hosts_response = list_hosts( self.apiclient, @@ -124,11 +105,11 @@ class TestPrimaryStorageServices(cloudstackTestCase): self.assertNotEqual( len(list_hosts_response), 0, - "Check list Hosts for hypervisor: " + v["hypervisor"] + "Check list Hosts in the cluster: " + cluster.name ) storage = StoragePool.create(self.apiclient, - v, + self.services["nfs"], clusterid=cluster.id, zoneid=self.zone.id, podid=self.pod.id @@ -140,13 +121,13 @@ class TestPrimaryStorageServices(cloudstackTestCase): self.assertEqual( storage.state, 'Up', - "Check primary storage state for hypervisor: " + v["hypervisor"] + "Check primary storage state " ) self.assertEqual( storage.type, 'NetworkFilesystem', - "Check storage pool type for hypervisor : " + v["hypervisor"] + "Check storage pool type " ) #Verify List Storage pool Response has newly added storage pool @@ -169,45 +150,76 @@ class TestPrimaryStorageServices(cloudstackTestCase): self.assertEqual( storage_response.id, storage.id, - "Check storage pool ID for hypervisor: " + v["hypervisor"] + "Check storage pool ID" ) self.assertEqual( storage.type, storage_response.type, - "Check storage pool type for hypervisor: " + v["hypervisor"] + "Check storage pool type " ) # Call cleanup for reusing primary storage cleanup_resources(self.apiclient, self.cleanup) self.cleanup = [] + return + + + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + def test_01_primary_storage_iscsi(self): + """Test primary storage pools - XEN, KVM, VMWare + """ + + # Validate the following: + # 1. List Clusters + # 2. verify that the cluster is in 'Enabled' allocation state + # 3. verify that the host is added successfully and + # in Up state with listHosts api response # Create iSCSI storage pools with on XEN/KVM clusters - for k, v in self.services["iscsi"].items(): - clusters = list_clusters( - self.apiclient, - zoneid=self.zone.id, - hypervisortype=v["hypervisor"] - ) + clusters = list_clusters( + self.apiclient, + zoneid=self.zone.id + ) + assert isinstance(clusters,list) and len(clusters)>0 + for cluster in clusters: + + #Host should be present before adding primary storage + list_hosts_response = list_hosts( + self.apiclient, + clusterid=cluster.id + ) self.assertEqual( - isinstance(clusters, list), + isinstance(list_hosts_response, list), True, "Check list response returns a valid list" ) - cluster = clusters[0] + + self.assertNotEqual( + len(list_hosts_response), + 0, + "Check list Hosts in the cluster: " + cluster + ) + storage = StoragePool.create(self.apiclient, - v, + self.services["iscsi"], clusterid=cluster.id, zoneid=self.zone.id, podid=self.pod.id ) self.cleanup.append(storage) - self.debug("Created iSCSI storage pool in cluster: %s" % cluster.id) - + self.debug("Created storage pool in cluster: %s" % cluster.id) + self.assertEqual( storage.state, 'Up', - "Check primary storage state for hypervisor: " + v["hypervisor"] + "Check primary storage state " + ) + + self.assertEqual( + storage.type, + 'NetworkFilesystem', + "Check storage pool type " ) #Verify List Storage pool Response has newly added storage pool @@ -221,24 +233,24 @@ class TestPrimaryStorageServices(cloudstackTestCase): "Check list response returns a valid list" ) self.assertNotEqual( - len(storage_pools_response), - 0, - "Check Hosts response for hypervisor: " + v["hypervisor"] + len(storage_pools_response), + 0, + "Check list Hosts response" ) storage_response = storage_pools_response[0] self.assertEqual( storage_response.id, storage.id, - "Check storage pool ID for hypervisor: " + v["hypervisor"] - ) + "Check storage pool ID" + ) self.assertEqual( storage.type, storage_response.type, - "Check storage pool type hypervisor: " + v["hypervisor"] + "Check storage pool type " ) - # Call cleanup for reusing primary storage cleanup_resources(self.apiclient, self.cleanup) self.cleanup = [] + return From 2e8d1264a247772b5dfda5bcab26fa5ed384a6d9 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 28 May 2013 09:43:23 +0200 Subject: [PATCH 169/201] CLOUDSTACK-2707: use executeBatch instead of persist when Usage Server createNetworkHelperEntry --- .../com/cloud/usage/dao/UsageNetworkDao.java | 2 ++ .../cloud/usage/dao/UsageNetworkDaoImpl.java | 34 +++++++++++++++++++ .../src/com/cloud/usage/UsageManagerImpl.java | 12 ++++--- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java index 0f7c771b2dc..aa43eab10e9 100644 --- a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java +++ b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.usage.dao; +import java.util.List; import java.util.Map; import com.cloud.usage.UsageNetworkVO; @@ -24,4 +25,5 @@ import com.cloud.utils.db.GenericDao; public interface UsageNetworkDao extends GenericDao { Map getRecentNetworkStats(); void deleteOldStats(long maxEventTime); + void saveUsageNetworks(List usageNetworks); } diff --git a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java index d64fd807890..af8083aa65a 100644 --- a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java +++ b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java @@ -19,6 +19,7 @@ package com.cloud.usage.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.ejb.Local; @@ -29,6 +30,7 @@ import org.springframework.stereotype.Component; import com.cloud.usage.UsageNetworkVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; @Component @Local(value={UsageNetworkDao.class}) @@ -41,6 +43,8 @@ public class UsageNetworkDaoImpl extends GenericDaoBase im ") joinnet on u.account_id = joinnet.acct_id and u.zone_id = joinnet.z_id and u.event_time_millis = joinnet.max_date"; private static final String DELETE_OLD_STATS = "DELETE FROM cloud_usage.usage_network WHERE event_time_millis < ?"; + private static final String INSERT_USAGE_NETWORK = "INSERT INTO cloud_usage.usage_network (account_id, zone_id, host_id, host_type, network_id, bytes_sent, bytes_received, agg_bytes_received, agg_bytes_sent, event_time_millis) VALUES (?,?,?,?,?,?,?,?,?,?)"; + public UsageNetworkDaoImpl() { } @@ -95,4 +99,34 @@ public class UsageNetworkDaoImpl extends GenericDaoBase im s_logger.error("error deleting old usage network stats", ex); } } + + @Override + public void saveUsageNetworks (List usageNetworks) { + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + String sql = INSERT_USAGE_NETWORK; + PreparedStatement pstmt = null; + pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection + for (UsageNetworkVO usageNetwork : usageNetworks) { + pstmt.setLong(1, usageNetwork.getAccountId()); + pstmt.setLong(2, usageNetwork.getZoneId()); + pstmt.setLong(3, usageNetwork.getHostId()); + pstmt.setString(4, usageNetwork.getHostType()); + pstmt.setLong(5, usageNetwork.getNetworkId()); + pstmt.setLong(6, usageNetwork.getBytesSent()); + pstmt.setLong(7, usageNetwork.getBytesReceived()); + pstmt.setLong(8, usageNetwork.getAggBytesReceived()); + pstmt.setLong(9, usageNetwork.getAggBytesSent()); + pstmt.setLong(10, usageNetwork.getEventTimeMillis()); + pstmt.addBatch(); + } + pstmt.executeBatch(); + txn.commit(); + } catch (Exception ex) { + txn.rollback(); + s_logger.error("error saving usage_network to cloud_usage db", ex); + throw new CloudRuntimeException(ex.getMessage()); + } + } } diff --git a/usage/src/com/cloud/usage/UsageManagerImpl.java b/usage/src/com/cloud/usage/UsageManagerImpl.java index 16fe67bcbec..0c2ad6ef339 100644 --- a/usage/src/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/com/cloud/usage/UsageManagerImpl.java @@ -18,6 +18,7 @@ package com.cloud.usage; import java.net.InetAddress; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -119,6 +120,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna int m_pid = 0; TimeZone m_usageTimezone = TimeZone.getTimeZone("GMT");; private final GlobalLock m_heartbeatLock = GlobalLock.getInternLock("usage.job.heartbeat.check"); + private List usageNetworks = new ArrayList(); private final ScheduledExecutorService m_executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Job")); private final ScheduledExecutorService m_heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-HB")); @@ -547,16 +549,18 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna // loop over the user stats, create delta entries in the usage_network helper table int numAcctsProcessed = 0; + usageNetworks.clear(); for (String key : aggregatedStats.keySet()) { UsageNetworkVO currentNetworkStats = null; if (networkStats != null) { currentNetworkStats = networkStats.get(key); } - + createNetworkHelperEntry(aggregatedStats.get(key), currentNetworkStats, endDateMillis); numAcctsProcessed++; - } - + } + m_usageNetworkDao.saveUsageNetworks(usageNetworks); + if (s_logger.isDebugEnabled()) { s_logger.debug("created network stats helper entries for " + numAcctsProcessed + " accts"); } @@ -999,7 +1003,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna s_logger.debug("creating networkHelperEntry... accountId: " + userStat.getAccountId() + " in zone: " + userStat.getDataCenterId() + "; abr: " + userStat.getAggBytesReceived() + "; abs: " + userStat.getAggBytesSent() + "; curABS: " + currentAccountedBytesSent + "; curABR: " + currentAccountedBytesReceived + "; ubs: " + bytesSent + "; ubr: " + bytesReceived); } - m_usageNetworkDao.persist(usageNetworkVO); + usageNetworks.add(usageNetworkVO); } private void createIPHelperEvent(UsageEventVO event) { From a0d5b78e84df705611f6e59df39ed7c7059c8b4d Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 28 May 2013 14:13:26 +0530 Subject: [PATCH 170/201] CLOUDSTACK-2708: AutoScale listConditions response wrongly mapped AutoScale - listConditions was mapped to CounterResponse instead of ConditionResponse Signed-off-by: Prasanna Santhanam --- .../api/command/user/autoscale/ListConditionsCmd.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java index 1c949232403..2b15d2b7e7d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java @@ -17,9 +17,7 @@ package org.apache.cloudstack.api.command.user.autoscale; -import java.util.ArrayList; -import java.util.List; - +import com.cloud.network.as.Condition; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListAccountResourcesCmd; @@ -30,9 +28,10 @@ import org.apache.cloudstack.api.response.CounterResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.log4j.Logger; -import com.cloud.network.as.Condition; +import java.util.ArrayList; +import java.util.List; -@APICommand(name = "listConditions", description = "List Conditions for the specific user", responseObject = CounterResponse.class) +@APICommand(name = "listConditions", description = "List Conditions for the specific user", responseObject = ConditionResponse.class) public class ListConditionsCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListConditionsCmd.class.getName()); private static final String s_name = "listconditionsresponse"; From 8ebf2ca3d74707b0006e6c6a667968a67520d346 Mon Sep 17 00:00:00 2001 From: radhikap Date: Tue, 28 May 2013 14:40:14 +0530 Subject: [PATCH 171/201] CLOUDSTACK-2709 --- docs/en-US/Release_Notes.xml | 6 ++++++ docs/en-US/egress-firewall-rule.xml | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index 25e1175b148..ab734cdf5d1 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -4396,6 +4396,12 @@ under the License.