Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive.Azure/HeuristicLab.Clients.Hive.CloudManager/3.3/Views/AddAzureServiceDialog.cs @ 8614

Last change on this file since 8614 was 8048, checked in by spimming, 13 years ago

#1680:

  • replaced instanceCount textbox with NumericUpDown control
  • fixed label position
  • removed unnecessary validation code
File size: 20.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.IO;
5using System.Net;
6using System.Text.RegularExpressions;
7using System.Windows.Forms;
8using HeuristicLab.Clients.Hive.CloudManager.Azure;
9using HeuristicLab.Clients.Hive.CloudManager.Model;
10using HeuristicLab.Core;
11using Microsoft.WindowsAzure;
12using Microsoft.WindowsAzure.StorageClient;
13
14namespace HeuristicLab.Clients.Hive.CloudManager.Views {
15  public partial class AddAzureServiceDialog : Form {
16    private BindingList<Subscription> subscriptions;
17    private BindingList<HostedService> hostedServices;
18    private BindingList<string> locations;
19    private BindingList<AffinityGroup> affinityGroups;
20    private BindingList<StorageService> storageServices;
21
22    private BackgroundWorker workerUpdate;
23    private BackgroundWorker workerCreate;
24
25    private bool isInitializing;
26    private bool bwCompleted;
27    private bool closePending;
28
29    private string certificateFile;
30    private string certificatePassword;
31
32    public AddAzureServiceDialog(IItemList<Subscription> subs) {
33      InitializeComponent();
34      isInitializing = true;
35      bwCompleted = true;
36
37      this.subscriptions = new BindingList<Subscription>(subs);
38      this.hostedServices = new BindingList<HostedService>();
39      this.locations = new BindingList<string>();
40      this.affinityGroups = new BindingList<AffinityGroup>();
41      this.storageServices = new BindingList<StorageService>();
42
43      SetLookupBinding(cmbLocation, locations, "", "");
44      SetLookupBinding(cmbAffinityGroup, affinityGroups, "Label", "Name");
45      SetLookupBinding(cmbChooseHostedService, hostedServices, "ServiceName", "ServiceName");
46      SetLookupBinding(cmbChooseSubscription, subscriptions, "SubscriptionName", "SubscriptionID");
47      SetLookupBinding(cmbStorageServices, storageServices, "ServiceName", "Url");
48
49      if (!cbNewHostedService.Checked) {
50        SetGroupBoxControlsEnabled(gbNewHostedService, cbNewHostedService.Checked);
51      }
52
53      certificateFile = string.Empty;
54      certificatePassword = string.Empty;
55
56      workerUpdate = new BackgroundWorker();
57      workerUpdate.DoWork += new DoWorkEventHandler(UpdateTask);
58      workerUpdate.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
59
60      workerCreate = new BackgroundWorker();
61      workerCreate.DoWork += new DoWorkEventHandler(CreateDeploymentTask);
62      workerCreate.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CreateDeploymentCompleted);
63
64      isInitializing = false;
65      cmbChooseSubscription_SelectedValueChanged(this, EventArgs.Empty);
66    }
67
68    protected override void OnFormClosing(FormClosingEventArgs e) {
69      if (!bwCompleted) {
70        SetAllControlsEnabled(this, false);
71        e.Cancel = true;
72        closePending = true;
73      }
74    }
75
76    private void SetLookupBinding(ListControl toBind, object dataSource, string displayMember, string valueMember) {
77      toBind.DisplayMember = displayMember;
78      toBind.ValueMember = valueMember;
79      toBind.DataSource = dataSource;
80    }
81
82    private void SetGroupBoxControlsEnabled(GroupBox gb, bool isEnabled) {
83      foreach (Control ctrl in gb.Controls) {
84        ctrl.Enabled = isEnabled;
85      }
86    }
87
88    private void SetAllControlsEnabled(Form frm, bool isEnabled) {
89      foreach (Control ctrl in frm.Controls) {
90        if (!(ctrl is ProgressBar)) {
91          ctrl.Enabled = isEnabled;
92        }
93      }
94    }
95
96    private void SetBindingList<T>(ref BindingList<T> bindinglist, List<T> list) {
97      if (list != null) {
98        BindingList<T> newList = new BindingList<T>(list);
99        bindinglist = newList;
100      }
101    }
102
103    private void UpdateBindingList<T>(BindingList<T> bindinglist, List<T> list) {
104      if (list != null) {
105        bindinglist.Clear();
106        foreach (T item in list)
107          bindinglist.Add(item);
108      }
109    }
110
111    private void UpdateSubscriptionItem(BindingList<Subscription> bindinglist, Subscription item) {
112      if (item != null) {
113        foreach (Subscription blItem in bindinglist)
114          if (blItem.Equals(item)) {
115            blItem.Merge(item);
116          }
117      }
118    }
119
120    private void cbNewHostedService_CheckedChanged(object sender, EventArgs e) {
121      if (cbNewHostedService.Checked) {
122        Subscription subscription = (Subscription)cmbChooseSubscription.SelectedItem;
123        if (subscription.CurrentHostedServices == subscription.MaxHostedServices) {
124          PluginInfrastructure.ErrorHandling.ShowErrorDialog(new Exception("You have already created the maximum number of hosted services"));
125          cbNewHostedService.Checked = false;
126        } else {
127          SetGroupBoxControlsEnabled(gbNewHostedService, cbNewHostedService.Checked);
128          cmbChooseHostedService.Enabled = false;
129        }
130      } else {
131        // checked == false
132        SetGroupBoxControlsEnabled(gbNewHostedService, false);
133        if (hostedServices.Count == 0) {
134          cbNewHostedService.Checked = true;
135        }
136      }
137    }
138
139    private void cmbChooseSubscription_SelectedValueChanged(object sender, EventArgs e) {
140      if (!isInitializing) {
141        Subscription item = (Subscription)cmbChooseSubscription.SelectedItem;
142        if (item != null) {
143          bwCompleted = false;
144          progressBar.Visible = true;
145          SetAllControlsEnabled(this, false);
146          workerUpdate.RunWorkerAsync(item);
147        }
148      }
149    }
150
151    private void btnAddCertificate_Click(object sender, EventArgs e) {
152      using (var form = new AddCertificate()) {
153        form.ShowDialog();
154        if (!form.ErrorOccured) {
155          certificateFile = form.CertificateFile;
156          certificatePassword = form.CertificatePassword;
157          lblCertificateFile.Text = certificateFile;
158        }
159      }
160    }
161
162    private void btnCancel_Click(object sender, EventArgs e) {
163      this.Close();
164    }
165
166    private void btnOk_Click(object sender, EventArgs e) {
167      if (cmbChooseSubscription.SelectedItem != null) {
168        Subscription sub = (Subscription)cmbChooseSubscription.SelectedItem;
169        // the controls collection can be the whole form or just a panel or group
170        if (Validation.hasValidationErrors(this.Controls)) {
171          return;
172        } else {
173          bool newHostedServiceChecked = cbNewHostedService.Checked;
174          bool regionChecked = rbRegion.Checked;
175          HostedService hostedService = null;
176          if (cbNewHostedService.Checked) {
177            hostedService = new HostedService();
178            hostedService.ServiceName = tbServiceName.Text;
179            HostedServiceProperties properties = new HostedServiceProperties();
180
181            if (regionChecked) {
182              properties.AffinityGroup = string.Empty;
183              properties.Location = (string)cmbLocation.SelectedItem;
184            } else {
185              properties.AffinityGroup = ((AffinityGroup)cmbAffinityGroup.SelectedItem).Name;
186              properties.Location = string.Empty;
187            }
188
189            if (cmbAffinityGroup.SelectedItem != null) {
190              properties.AffinityGroup = ((AffinityGroup)cmbAffinityGroup.SelectedItem).Name;
191            }
192            properties.Label = tbLabel.Text;
193            properties.Location = (string)cmbLocation.SelectedItem;
194            hostedService.HostedServiceProperties = properties;
195          } else {
196            hostedService = (HostedService)cmbChooseHostedService.SelectedItem;
197          }
198
199
200          string certFile = certificateFile;
201          string certPw = certificatePassword;
202          //int instanceCount = Convert.ToInt32(tbInstanceCount.Text);
203          int instanceCount = Convert.ToInt32(instancesNumericUpDown.Value);
204
205
206
207          string packagefilepath = string.Empty;
208          if (rbVMSizeSmall.Checked) {
209            packagefilepath = Constants.DeploymentPackagePathSmall;
210          } else if (rbVMSizeMedium.Checked) {
211            packagefilepath = Constants.DeploymentPackagePathMedium;
212          } else if (rbVMSizeLarge.Checked) {
213            packagefilepath = Constants.DeploymentPackagePathLarge;
214          } else if (rbVMSizeExtraLarge.Checked) {
215            packagefilepath = Constants.DeploymentPackagePathExtraLarge;
216          }
217
218          string deploymentSlot = string.Empty;
219          if (rbDeployToProduction.Checked) {
220            deploymentSlot = Constants.DeploymentSlotProduction;
221          } else if (rbDeployToStaging.Checked) {
222            deploymentSlot = Constants.DeploymentSlotStaging;
223          }
224
225          //var parameters1 = Tuple.Create<Subscription, bool, bool, string, string, HostedService, int>
226          //  (sub, newHostedServiceChecked, regionChecked, certificateFile, certificatePassword, hostedService, instanceCount);
227          CreateDeploymentData parameters = new CreateDeploymentData();
228          parameters.Subscription = sub;
229          parameters.CreateNewHosteService = newHostedServiceChecked;
230          parameters.UseRegion = regionChecked;
231          parameters.CertificateFilePath = certificateFile;
232          parameters.CertificatePassword = certificatePassword;
233          parameters.HostedService = hostedService;
234          parameters.InstanceCount = instanceCount;
235          parameters.StorageService = (StorageService)cmbStorageServices.SelectedItem;
236          parameters.CreateContainerIfNotExists = cbCreateBlobIfNotExists.Checked;
237          parameters.BlobContainerName = tbBlobContainer.Text;
238          parameters.DeploymentPackageFilePath = packagefilepath;
239          parameters.DeploymentSlot = deploymentSlot;
240
241          bwCompleted = false;
242          progressBar.Visible = true;
243          SetAllControlsEnabled(this, false);
244          workerCreate.RunWorkerAsync(parameters);
245        }
246      }
247    }
248
249    private void UpdateTask(object sender, DoWorkEventArgs e) {
250      try {
251        Subscription item = (Subscription)e.Argument;
252        item = CloudManagerClient.Instance.AzureProvider.GetSubscriptionInfo(item.SubscriptionID, item.CertificateThumbprint);
253        this.Invoke((MethodInvoker)delegate {
254          lblCores.Text = item.CurrentCoreCount + " / " + item.MaxCoreCount;
255          instancesNumericUpDown.Maximum = item.MaxCoreCount;
256        });
257
258        List<HostedService> services = CloudManagerClient.Instance.AzureProvider.ListHostedServices(item);
259        List<string> locs = CloudManagerClient.Instance.AzureProvider.ListLocations(item);
260        List<AffinityGroup> groups = CloudManagerClient.Instance.AzureProvider.ListAffinityGroups(item);
261        List<StorageService> storage = CloudManagerClient.Instance.AzureProvider.ListStorageServices(item);
262
263        this.Invoke((MethodInvoker)delegate { UpdateSubscriptionItem(subscriptions, item); });
264        this.Invoke((MethodInvoker)delegate { UpdateBindingList<HostedService>(hostedServices, services); });
265        this.Invoke((MethodInvoker)delegate { UpdateBindingList<string>(locations, locs); });
266        this.Invoke((MethodInvoker)delegate { UpdateBindingList<AffinityGroup>(affinityGroups, groups); });
267        this.Invoke((MethodInvoker)delegate { UpdateBindingList<StorageService>(storageServices, storage); });
268      }
269      catch (Exception ex) {
270        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
271      }
272    }
273
274    private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
275      SetAllControlsEnabled(this, true);
276      progressBar.Visible = false;
277      bwCompleted = true;
278      if (closePending) {
279        this.Close();
280      }
281    }
282
283    private void CreateDeploymentTask(object sender, DoWorkEventArgs e) {
284      bool errorOccured = false;
285      CreateDeploymentData parameters = (CreateDeploymentData)e.Argument;
286
287      Subscription sub = parameters.Subscription;
288      bool newHostedServiceChecked = parameters.CreateNewHosteService;
289      bool regionChecked = parameters.UseRegion;
290      string certFile = parameters.CertificateFilePath;
291      string certPw = parameters.CertificatePassword;
292      HostedService hostedService = parameters.HostedService;
293      int instanceCount = parameters.InstanceCount;
294      StorageService storageService = parameters.StorageService;
295      string blobContainerName = parameters.BlobContainerName;
296      bool createContainerIfNotExists = parameters.CreateContainerIfNotExists;
297      string packageFilePath = parameters.DeploymentPackageFilePath;
298      FileInfo packageFile = new FileInfo(packageFilePath);
299      string deploymentSlot = parameters.DeploymentSlot;
300
301      int defaultCollectionLimit = ServicePointManager.DefaultConnectionLimit;
302
303      CloudStorageAccount storageAccount = null; ;
304      CloudBlobClient blobClient = null;
305      CloudBlobContainer blobContainer = null;
306
307      // STEP 1 - Initialize storage account
308      try {
309        StorageServiceKeys keys = CloudManagerClient.Instance.AzureProvider.GetStorageKeys(sub, storageService.ServiceName);
310        storageAccount = CloudStorageAccount.Parse(string.Format(Constants.StorageServiceConnectionFormat, storageService.ServiceName, keys.Primary));
311        blobClient = storageAccount.CreateCloudBlobClient();
312        blobContainer = blobClient.GetContainerReference(blobContainerName);
313        if (createContainerIfNotExists) {
314          blobContainer.CreateIfNotExist();
315        } else {
316          if (!blobContainer.Exists()) {
317            throw new ApplicationException("Specified blob container doesn't exist.");
318          }
319        }
320      }
321      catch (Exception ex) {
322        errorOccured = true;
323        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
324      }
325
326      // STEP 2 - Copy service package file to storage account
327      CloudBlockBlob blobPackage = null;
328      try {
329        blobPackage = blobContainer.GetBlockBlobReference(packageFile.Name);
330        if (!blobPackage.Exists()) {
331          ServicePointManager.DefaultConnectionLimit = 64;
332          blobPackage.UploadParallel(packageFile.FullName);
333        }
334
335      }
336      catch (Exception ex) {
337        errorOccured = true;
338        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
339      }
340
341
342      // STEP 1 - Create Hosted Service
343      try {
344        if ((!errorOccured) && (newHostedServiceChecked)) {
345          if (regionChecked) {
346            CloudManagerClient.Instance.AzureProvider.CreateHostedService(sub, hostedService.ServiceName, hostedService.HostedServiceProperties.Label, hostedService.HostedServiceProperties.Description, hostedService.HostedServiceProperties.Location);
347          } else {
348            CloudManagerClient.Instance.AzureProvider.CreateHostedService(sub, hostedService.ServiceName, hostedService.HostedServiceProperties.Label, hostedService.HostedServiceProperties.Description, new AffinityGroup() { Name = hostedService.HostedServiceProperties.AffinityGroup });
349          }
350        }
351      }
352      catch (Exception ex) {
353        errorOccured = true;
354        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
355      }
356
357      // STEP 2 - Add Certificate
358      try {
359        if ((!errorOccured) && (certFile != string.Empty)) {
360          CloudManagerClient.Instance.AzureProvider.AddCertificate(sub, hostedService, certFile, certPw);
361        }
362      }
363      catch (Exception ex) {
364        errorOccured = true;
365        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
366        if (newHostedServiceChecked) {
367          CloudManagerClient.Instance.AzureProvider.DeleteHostedService(sub, hostedService.ServiceName);
368        }
369
370      }
371
372      // STEP 3 - Create Deployment
373      try {
374        if (!errorOccured) {
375          //CloudManagerClient.Instance.AzureProvider.CreateDeployment(sub, hostedService.ServiceName, Guid.NewGuid().ToString(), Constants.DeploymentSlotStaging, Constants.DeploymentPackageUrl, Constants.DeploymentConfigurationUrl, Constants.DeploymentLabel, instanceCount);
376          CloudManagerClient.Instance.AzureProvider.CreateDeployment(sub, hostedService.ServiceName, Guid.NewGuid().ToString(), deploymentSlot, blobPackage.Uri.ToString(), new FileInfo(Constants.DeploymentConfigurationPath), Constants.DeploymentLabel, instanceCount);
377        }
378      }
379      catch (Exception ex) {
380        errorOccured = true;
381        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
382        if (newHostedServiceChecked) {
383          CloudManagerClient.Instance.AzureProvider.DeleteHostedService(sub, hostedService.ServiceName);
384        }
385      }
386
387      ServicePointManager.DefaultConnectionLimit = defaultCollectionLimit;
388      e.Result = errorOccured;
389    }
390
391    private void CreateDeploymentCompleted(object sender, RunWorkerCompletedEventArgs e) {
392      SetAllControlsEnabled(this, true);
393      progressBar.Visible = false;
394      bwCompleted = true;
395      bool errorOccured = (bool)e.Result;
396      if (closePending) {
397        this.Close();
398      } else if (!errorOccured) {
399        this.Close();
400      } else {
401        this.Show();
402      }
403    }
404
405    private void tbServiceName_Validating(object sender, CancelEventArgs e) {
406      if (cbNewHostedService.Checked) {
407        string url = tbServiceName.Text.Trim();
408        if (url == String.Empty) {
409          errorProvider.SetError(tbServiceName, "A URL is required for the hosted service.");
410          e.Cancel = true;
411        } else if (!isValidHostedServiceUrl(url)) {
412          errorProvider.SetError(tbServiceName, "A hosted service name must be between 1 and 63 " +
413                                                "characters long, and be composed of letters, numbers " +
414                                                "and hyphens. Hyphens shouldn't be first or last letter.");
415          e.Cancel = true;
416        } else {
417          errorProvider.SetError(tbServiceName, "");
418        }
419      }
420    }
421
422    private void tbLabel_Validating(object sender, CancelEventArgs e) {
423      if (cbNewHostedService.Checked) {
424        if (tbLabel.Text.Trim() == String.Empty) {
425          errorProvider.SetError(tbLabel, "A name is required for the hosted service.");
426          e.Cancel = true;
427        } else {
428          errorProvider.SetError(tbLabel, "");
429        }
430      }
431    }
432
433    private bool isValidHostedServiceUrl(string url) {
434      string regexString = @"[a-zA-Z0-9]+[a-zA-Z0-9-]{0,61}[a-zA-Z0-9]+";  //TODO
435      Regex regex = new Regex(regexString);
436      if (regex.IsMatch(url)) {
437        return true;
438      } else {
439        return false;
440      }
441    }
442
443    private bool isValidStorageContainerName(string name) {
444      string regexString = @"[a-z0-9]+[a-z0-9-]{0,61}[a-z0-9]+";  //TODO
445      Regex regex = new Regex(regexString);
446      if (regex.IsMatch(name)) {
447        return true;
448      } else {
449        return false;
450      }
451    }
452
453    private void tbBlobContainer_Validating(object sender, CancelEventArgs e) {
454      string name = tbBlobContainer.Text.Trim();
455      if (name == string.Empty) {
456        errorProvider.SetError(tbBlobContainer, "A name is required for the blob container.");
457        e.Cancel = true;
458      } else if (!isValidStorageContainerName(name)) {
459        errorProvider.SetError(tbBlobContainer, "A blob container name must be between 1 and 63 " +
460                                              "characters long, and be composed of lowercase letters, numbers " +
461                                              "and hyphens. Hyphens shouldn't be first or last letter.");
462        e.Cancel = true;
463      } else {
464        errorProvider.SetError(tbBlobContainer, "");
465      }
466    }
467
468    private void cmbChooseHostedService_Validating(object sender, CancelEventArgs e) {
469      if ((!cbNewHostedService.Checked) && (cmbChooseHostedService.SelectedItem == null)) {
470        errorProvider.SetError(cmbChooseHostedService, "A hoste service is required.");
471        e.Cancel = true;
472      } else {
473        errorProvider.SetError(cmbChooseHostedService, "");
474      }
475    }
476
477    private void cmbStorageServices_Validating(object sender, CancelEventArgs e) {
478      if (cmbStorageServices.SelectedItem == null) {
479        errorProvider.SetError(cmbStorageServices, "A storage service is required.");
480        e.Cancel = true;
481      } else {
482        errorProvider.SetError(cmbStorageServices, "");
483      }
484    }
485
486    private class CreateDeploymentData {
487      public Subscription Subscription { get; set; }
488      public bool CreateNewHosteService { get; set; }
489      public bool UseRegion { get; set; }
490      public string CertificateFilePath { get; set; }
491      public string CertificatePassword { get; set; }
492      public HostedService HostedService { get; set; }
493      public int InstanceCount { get; set; }
494      public StorageService StorageService { get; set; }
495      public string BlobContainerName { get; set; }
496      public bool CreateContainerIfNotExists { get; set; }
497      public string DeploymentPackageFilePath { get; set; }
498      public string DeploymentSlot { get; set; }
499    }
500  }
501}
Note: See TracBrowser for help on using the repository browser.