Просмотр исходного кода

Label change with retry in helpers

almahmoud 7 лет назад
Родитель
Сommit
98fa283777
2 измененных файлов с 87 добавлено и 147 удалено
  1. 36 0
      cloudbridge/cloud/providers/gce/helpers.py
  2. 51 147
      cloudbridge/cloud/providers/gce/resources.py

+ 36 - 0
cloudbridge/cloud/providers/gce/helpers.py

@@ -143,3 +143,39 @@ def remove_metadata_item(provider, key):
 
 
     gce_metadata_save_op(provider, _remove_metadata_by_key)
     gce_metadata_save_op(provider, _remove_metadata_by_key)
     return True
     return True
+
+
+def __if_label_fingerprint_differs(e):
+    # return True if the CloudError exception is due to subnet being in use
+    if isinstance(e, HttpError):
+        expected_message = 'Labels fingerprint either invalid or ' \
+                           'resource labels have changed'
+        # str wrapper required for Python 2.7
+        if expected_message in str(e.content):
+            return True
+    return False
+
+
+@tenacity.retry(stop=tenacity.stop_after_attempt(10),
+                retry=tenacity.retry_if_exception(
+                    __if_label_fingerprint_differs),
+                wait=tenacity.wait_exponential(max=10),
+                reraise=True)
+def change_label(resource, key, value, res_att, request):
+    resource.assert_valid_resource_label(value)
+    labels = getattr(resource, res_att).get("labels", {})
+    print(labels)
+    labels[key] = value
+    request_body = {
+        "labels": labels,
+        "labelFingerprint":
+            getattr(resource, res_att).get('labelFingerprint'),
+    }
+    try:
+        request.body = str(request_body)
+        request.body_size = len(str(request_body))
+        response = request.execute()
+        resource._provider.wait_for_operation(response,
+                                              zone=resource.zone_name)
+    finally:
+        resource.refresh()

+ 51 - 147
cloudbridge/cloud/providers/gce/resources.py

@@ -473,7 +473,6 @@ class GCEVMFirewall(BaseVMFirewall):
     def label(self):
     def label(self):
         tag_name = "_".join(["firewall", self.name, "label"])
         tag_name = "_".join(["firewall", self.name, "label"])
         return helpers.get_metadata_item_value(self._provider, tag_name)
         return helpers.get_metadata_item_value(self._provider, tag_name)
-        # TODO: Add removing metadata to delete function
 
 
     @label.setter
     @label.setter
     def label(self, value):
     def label(self, value):
@@ -764,30 +763,14 @@ class GCEMachineImage(BaseMachineImage):
     @label.setter
     @label.setter
     # pylint:disable=arguments-differ
     # pylint:disable=arguments-differ
     def label(self, value):
     def label(self, value):
-        self.assert_valid_resource_label(value)
-        # Refresh to update fingerprint and current labels
-        self.refresh()
-        labels = self._gce_image.get('labels', {})
-        labels['cblabel'] = value
-        request_body = {
-            'labels': labels,
-            'labelFingerprint': self._gce_image.get('labelFingerprint'),
-        }
-        try:
-            response = (self._provider
-                        .gce_compute
-                        .images()
-                        .setLabels(project=self._provider.project_name,
-                                   resource=self.name,
-                                   body=request_body)
-                        .execute())
-            self._provider.wait_for_operation(response)
-        except Exception as e:
-            cb.log.warning('Exception while setting image label: %s. '
-                           'Check for invalid characters in label. '
-                           'Should conform to RFC1035.', e)
-            raise e
-        self.refresh()
+        req = (self._provider
+                   .gce_compute
+                   .images()
+                   .setLabels(project=self._provider.project_name,
+                              resource=self.name,
+                              body={}))
+
+        helpers.change_label(self, 'cblabel', value, '_gce_image', req)
 
 
     @property
     @property
     def description(self):
     def description(self):
@@ -887,31 +870,15 @@ class GCEInstance(BaseInstance):
     @label.setter
     @label.setter
     # pylint:disable=arguments-differ
     # pylint:disable=arguments-differ
     def label(self, value):
     def label(self, value):
-        self.assert_valid_resource_label(value)
-        # Refresh to update fingerprint and current labels
-        self.refresh()
-        labels = self._gce_instance.get('labels', {})
-        labels['cblabel'] = value
-        request_body = {
-            'labels': labels,
-            'labelFingerprint': self._gce_instance.get('labelFingerprint'),
-        }
-        try:
-            response = (self._provider
-                        .gce_compute
-                        .instances()
-                        .setLabels(project=self._provider.project_name,
-                                   zone=self.zone_name,
-                                   instance=self.name,
-                                   body=request_body)
-                        .execute())
-            self._provider.wait_for_operation(response, zone=self.zone_name)
-        except Exception as e:
-            cb.log.warning('Exception while setting instance label: %s. '
-                           'Check for invalid characters in label. '
-                           'Should conform to RFC1035.', e)
-            raise e
-        self.refresh()
+        req = (self._provider
+                   .gce_compute
+                   .instances()
+                   .setLabels(project=self._provider.project_name,
+                              zone=self.zone_name,
+                              instance=self.name,
+                              body={}))
+
+        helpers.change_label(self, 'cblabel', value, '_gce_instance', req)
 
 
     @property
     @property
     def public_ips(self):
     def public_ips(self):
@@ -1842,31 +1809,15 @@ class GCEVolume(BaseVolume):
 
 
     @label.setter
     @label.setter
     def label(self, value):
     def label(self, value):
-        self.assert_valid_resource_label(value)
-        # Refresh to update fingerprint and current labels
-        self.refresh()
-        labels = self._volume.get('labels', {})
-        labels['cblabel'] = value
-        request_body = {
-            'labels': labels,
-            'labelFingerprint': self._volume.get('labelFingerprint'),
-        }
-        try:
-            response = (self._provider
-                        .gce_compute
-                        .disks()
-                        .setLabels(project=self._provider.project_name,
-                                   zone=self.zone_name,
-                                   resource=self.name,
-                                   body=request_body)
-                        .execute())
-            self._provider.wait_for_operation(response, zone=self.zone_name)
-        except Exception as e:
-            cb.log.warning('Exception while setting volume name: %s. '
-                           'Check for invalid characters in name. '
-                           'Should conform to RFC1035.', e)
-            raise e
-        self.refresh()
+        req = (self._provider
+                   .gce_compute
+                   .disks()
+                   .setLabels(project=self._provider.project_name,
+                              zone=self.zone_name,
+                              resource=self.name,
+                              body={}))
+
+        helpers.change_label(self, 'cblabel', value, '_volume', req)
 
 
     @property
     @property
     def description(self):
     def description(self):
@@ -1877,31 +1828,15 @@ class GCEVolume(BaseVolume):
 
 
     @description.setter
     @description.setter
     def description(self, value):
     def description(self, value):
-        # Refresh to update fingerprint and current labels
-        self.refresh()
-        labels = self._volume.get('labels', {})
-        labels['description'] = value.replace(' ', '_').lower()
-        request_body = {
-            'labels': labels,
-            'labelFingerprint': self._volume.get('labelFingerprint'),
-        }
-        try:
-            response = (self._provider
-                        .gce_compute
-                        .disks()
-                        .setLabels(project=self._provider.project_name,
-                                   zone=self.zone_name,
-                                   resource=self.name,
-                                   body=request_body)
-                        .execute())
-            self._provider.wait_for_operation(response,
-                                              zone=self.zone_name)
-        except Exception as e:
-            cb.log.warning('Exception while setting volume description: %s. '
-                           'Check for invalid characters in description. '
-                           'Should confirm to RFC1035.', e)
-            raise e
-        self.refresh()
+        req = (self._provider
+               .gce_compute
+               .disks()
+               .setLabels(project=self._provider.project_name,
+                          zone=self.zone_name,
+                          resource=self.name,
+                          body={}))
+
+        helpers.change_label(self, 'description', value, '_volume', req)
 
 
     @property
     @property
     def size(self):
     def size(self):
@@ -2072,30 +2007,14 @@ class GCESnapshot(BaseSnapshot):
     @label.setter
     @label.setter
     # pylint:disable=arguments-differ
     # pylint:disable=arguments-differ
     def label(self, value):
     def label(self, value):
-        self.assert_valid_resource_label(value)
-        # Refresh to update fingerprint and current labels
-        self.refresh()
-        labels = self._snapshot.get('labels', {})
-        labels['cblabel'] = value
-        request_body = {
-            'labels': labels,
-            'labelFingerprint': self._snapshot.get('labelFingerprint'),
-        }
-        try:
-            response = (self._provider
-                        .gce_compute
-                        .snapshots()
-                        .setLabels(project=self._provider.project_name,
-                                   resource=self.name,
-                                   body=request_body)
-                        .execute())
-            self._provider.wait_for_operation(response)
-        except Exception as e:
-            cb.log.warning('Exception while setting snapshot label: %s. '
-                           'Check for invalid characters in label. '
-                           'Should conform to RFC1035.', e)
-            raise e
-        self.refresh()
+        req = (self._provider
+                   .gce_compute
+                   .snapshots()
+                   .setLabels(project=self._provider.project_name,
+                              resource=self.name,
+                              body={}))
+
+        helpers.change_label(self, 'cblabel', value, '_snapshot', req)
 
 
     @property
     @property
     def description(self):
     def description(self):
@@ -2106,29 +2025,14 @@ class GCESnapshot(BaseSnapshot):
 
 
     @description.setter
     @description.setter
     def description(self, value):
     def description(self, value):
-        # Refresh to update fingerprint and current labels
-        self.refresh()
-        labels = self._snapshot.get('labels', {})
-        labels['description'] = value.replace(' ', '_').lower()
-        request_body = {
-            'labels': labels,
-            'labelFingerprint': self._snapshot.get('labelFingerprint'),
-        }
-        try:
-            response = (self._provider
-                        .gce_compute
-                        .snapshots()
-                        .setLabels(project=self._provider.project_name,
-                                   resource=self.name,
-                                   body=request_body)
-                        .execute())
-            self._provider.wait_for_operation(response)
-        except Exception as e:
-            cb.log.warning('Exception while setting volume description: %s. '
-                           'Check for invalid characters in description. '
-                           'Should confirm to RFC1035.', e)
-            raise e
-        self.refresh()
+        req = (self._provider
+               .gce_compute
+               .snapshots()
+               .setLabels(project=self._provider.project_name,
+                          resource=self.name,
+                          body={}))
+
+        helpers.change_label(self, 'description', value, '_snapshot', req)
 
 
     @property
     @property
     def size(self):
     def size(self):