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
RevLine 
[7339]1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
[7565]4using System.IO;
5using System.Net;
[7424]6using System.Text.RegularExpressions;
[7339]7using System.Windows.Forms;
[7374]8using HeuristicLab.Clients.Hive.CloudManager.Azure;
[7339]9using HeuristicLab.Clients.Hive.CloudManager.Model;
10using HeuristicLab.Core;
[7551]11using Microsoft.WindowsAzure;
12using Microsoft.WindowsAzure.StorageClient;
[7339]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;
[7551]20    private BindingList<StorageService> storageServices;
[7339]21
[7366]22    private BackgroundWorker workerUpdate;
23    private BackgroundWorker workerCreate;
[7339]24
[7354]25    private bool isInitializing;
26    private bool bwCompleted;
27    private bool closePending;
28
[7362]29    private string certificateFile;
30    private string certificatePassword;
31
[7339]32    public AddAzureServiceDialog(IItemList<Subscription> subs) {
33      InitializeComponent();
[7354]34      isInitializing = true;
[7357]35      bwCompleted = true;
[7339]36
37      this.subscriptions = new BindingList<Subscription>(subs);
[7354]38      this.hostedServices = new BindingList<HostedService>();
39      this.locations = new BindingList<string>();
40      this.affinityGroups = new BindingList<AffinityGroup>();
[7551]41      this.storageServices = new BindingList<StorageService>();
[7339]42
[7354]43      SetLookupBinding(cmbLocation, locations, "", "");
44      SetLookupBinding(cmbAffinityGroup, affinityGroups, "Label", "Name");
45      SetLookupBinding(cmbChooseHostedService, hostedServices, "ServiceName", "ServiceName");
[7339]46      SetLookupBinding(cmbChooseSubscription, subscriptions, "SubscriptionName", "SubscriptionID");
[7551]47      SetLookupBinding(cmbStorageServices, storageServices, "ServiceName", "Url");
[7339]48
49      if (!cbNewHostedService.Checked) {
50        SetGroupBoxControlsEnabled(gbNewHostedService, cbNewHostedService.Checked);
51      }
52
[7374]53      certificateFile = string.Empty;
54      certificatePassword = string.Empty;
55
[7366]56      workerUpdate = new BackgroundWorker();
57      workerUpdate.DoWork += new DoWorkEventHandler(UpdateTask);
58      workerUpdate.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
[7354]59
[7366]60      workerCreate = new BackgroundWorker();
[7551]61      workerCreate.DoWork += new DoWorkEventHandler(CreateDeploymentTask);
[7366]62      workerCreate.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CreateDeploymentCompleted);
[7354]63
64      isInitializing = false;
65      cmbChooseSubscription_SelectedValueChanged(this, EventArgs.Empty);
[7339]66    }
67
[7354]68    protected override void OnFormClosing(FormClosingEventArgs e) {
69      if (!bwCompleted) {
[7357]70        SetAllControlsEnabled(this, false);
[7354]71        e.Cancel = true;
72        closePending = true;
73      }
74    }
75
[7339]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)) {
[7357]91          ctrl.Enabled = isEnabled;
[7339]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
[7354]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
[7366]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
[7339]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) {
[7661]124          PluginInfrastructure.ErrorHandling.ShowErrorDialog(new Exception("You have already created the maximum number of hosted services"));
[7339]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);
[7357]133        if (hostedServices.Count == 0) {
[7339]134          cbNewHostedService.Checked = true;
135        }
136      }
137    }
138
139    private void cmbChooseSubscription_SelectedValueChanged(object sender, EventArgs e) {
[7354]140      if (!isInitializing) {
141        Subscription item = (Subscription)cmbChooseSubscription.SelectedItem;
142        if (item != null) {
[7357]143          bwCompleted = false;
[7354]144          progressBar.Visible = true;
[7357]145          SetAllControlsEnabled(this, false);
[7366]146          workerUpdate.RunWorkerAsync(item);
[7354]147        }
[7339]148      }
149    }
150
151    private void btnAddCertificate_Click(object sender, EventArgs e) {
152      using (var form = new AddCertificate()) {
153        form.ShowDialog();
[7362]154        if (!form.ErrorOccured) {
155          certificateFile = form.CertificateFile;
156          certificatePassword = form.CertificatePassword;
157          lblCertificateFile.Text = certificateFile;
158        }
[7339]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) {
[7366]168        Subscription sub = (Subscription)cmbChooseSubscription.SelectedItem;
[7424]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 {
[7387]173          bool newHostedServiceChecked = cbNewHostedService.Checked;
174          bool regionChecked = rbRegion.Checked;
[7565]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
[7387]200          string certFile = certificateFile;
201          string certPw = certificatePassword;
[8048]202          //int instanceCount = Convert.ToInt32(tbInstanceCount.Text);
203          int instanceCount = Convert.ToInt32(instancesNumericUpDown.Value);
[7565]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;
[7387]216          }
217
[7565]218          string deploymentSlot = string.Empty;
219          if (rbDeployToProduction.Checked) {
220            deploymentSlot = Constants.DeploymentSlotProduction;
221          } else if (rbDeployToStaging.Checked) {
222            deploymentSlot = Constants.DeploymentSlotStaging;
[7421]223          }
[7366]224
[7551]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;
[7565]236          parameters.CreateContainerIfNotExists = cbCreateBlobIfNotExists.Checked;
[7551]237          parameters.BlobContainerName = tbBlobContainer.Text;
[7565]238          parameters.DeploymentPackageFilePath = packagefilepath;
239          parameters.DeploymentSlot = deploymentSlot;
[7366]240
[7387]241          bwCompleted = false;
242          progressBar.Visible = true;
243          SetAllControlsEnabled(this, false);
244          workerCreate.RunWorkerAsync(parameters);
245        }
[7339]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);
[8048]253        this.Invoke((MethodInvoker)delegate {
254          lblCores.Text = item.CurrentCoreCount + " / " + item.MaxCoreCount;
255          instancesNumericUpDown.Maximum = item.MaxCoreCount;
256        });
[7339]257
[7354]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);
[7551]261        List<StorageService> storage = CloudManagerClient.Instance.AzureProvider.ListStorageServices(item);
[7339]262
[7366]263        this.Invoke((MethodInvoker)delegate { UpdateSubscriptionItem(subscriptions, item); });
[7354]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); });
[7551]267        this.Invoke((MethodInvoker)delegate { UpdateBindingList<StorageService>(storageServices, storage); });
[7339]268      }
269      catch (Exception ex) {
[7661]270        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
[7339]271      }
272    }
273
274    private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
[7357]275      SetAllControlsEnabled(this, true);
276      progressBar.Visible = false;
[7354]277      bwCompleted = true;
278      if (closePending) {
279        this.Close();
280      }
[7339]281    }
[7366]282
[7551]283    private void CreateDeploymentTask(object sender, DoWorkEventArgs e) {
[7387]284      bool errorOccured = false;
[7551]285      CreateDeploymentData parameters = (CreateDeploymentData)e.Argument;
[7366]286
[7551]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;
[7565]297      string packageFilePath = parameters.DeploymentPackageFilePath;
298      FileInfo packageFile = new FileInfo(packageFilePath);
299      string deploymentSlot = parameters.DeploymentSlot;
[7366]300
[7565]301      int defaultCollectionLimit = ServicePointManager.DefaultConnectionLimit;
[7551]302
[7565]303      CloudStorageAccount storageAccount = null; ;
304      CloudBlobClient blobClient = null;
305      CloudBlobContainer blobContainer = null;
306
[7551]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;
[7661]323        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
[7551]324      }
325
[7565]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        }
[7551]334
[7565]335      }
336      catch (Exception ex) {
337        errorOccured = true;
[7661]338        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
[7565]339      }
340
341
[7374]342      // STEP 1 - Create Hosted Service
[7387]343      try {
[7551]344        if ((!errorOccured) && (newHostedServiceChecked)) {
[7387]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          }
[7366]350        }
351      }
[7387]352      catch (Exception ex) {
353        errorOccured = true;
[7661]354        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
[7387]355      }
[7366]356
[7374]357      // STEP 2 - Add Certificate
[7387]358      try {
359        if ((!errorOccured) && (certFile != string.Empty)) {
360          CloudManagerClient.Instance.AzureProvider.AddCertificate(sub, hostedService, certFile, certPw);
361        }
[7374]362      }
[7387]363      catch (Exception ex) {
364        errorOccured = true;
[7661]365        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
[7387]366        if (newHostedServiceChecked) {
367          CloudManagerClient.Instance.AzureProvider.DeleteHostedService(sub, hostedService.ServiceName);
368        }
[7374]369
[7387]370      }
371
[7374]372      // STEP 3 - Create Deployment
[7387]373      try {
374        if (!errorOccured) {
[7565]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);
[7387]377        }
378      }
379      catch (Exception ex) {
380        errorOccured = true;
[7661]381        PluginInfrastructure.ErrorHandling.ShowErrorDialog(ex);
[7387]382        if (newHostedServiceChecked) {
383          CloudManagerClient.Instance.AzureProvider.DeleteHostedService(sub, hostedService.ServiceName);
384        }
385      }
[7374]386
[7565]387      ServicePointManager.DefaultConnectionLimit = defaultCollectionLimit;
[7387]388      e.Result = errorOccured;
[7366]389    }
390
391    private void CreateDeploymentCompleted(object sender, RunWorkerCompletedEventArgs e) {
392      SetAllControlsEnabled(this, true);
393      progressBar.Visible = false;
394      bwCompleted = true;
[7387]395      bool errorOccured = (bool)e.Result;
[7366]396      if (closePending) {
397        this.Close();
[7387]398      } else if (!errorOccured) {
399        this.Close();
400      } else {
401        this.Show();
[7366]402      }
403    }
[7424]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)) {
[7429]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.");
[7424]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    }
[7429]442
[7551]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; }
[7565]497      public string DeploymentPackageFilePath { get; set; }
498      public string DeploymentSlot { get; set; }
[7551]499    }
[7339]500  }
501}
Note: See TracBrowser for help on using the repository browser.