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

Initial updates to support name and label + misc fixes

Nuwan Goonasekera 7 лет назад
Родитель
Сommit
04b77f69aa

+ 1 - 1
cloudbridge/cloud/providers/gce/provider.py

@@ -199,7 +199,7 @@ class GCECloudProvider(BaseCloudProvider):
 
 
         # Disable warnings about file_cache not being available when using
         # Disable warnings about file_cache not being available when using
         # oauth2client >= 4.0.0.
         # oauth2client >= 4.0.0.
-        logging.getLogger('googleapicliet.discovery_cache').setLevel(
+        logging.getLogger('googleapiclient.discovery_cache').setLevel(
                 logging.ERROR)
                 logging.ERROR)
 
 
         # Initialize cloud connection fields
         # Initialize cloud connection fields

+ 238 - 44
cloudbridge/cloud/providers/gce/resources.py

@@ -740,6 +740,35 @@ class GCEMachineImage(BaseMachineImage):
         """
         """
         return self._gce_image['name']
         return self._gce_image['name']
 
 
+    @property
+    def label(self):
+        labels = self._gce_image.get('labels')
+        return labels.get('cblabel', '') if labels else ''
+
+    @label.setter
+    # pylint:disable=arguments-differ
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        request_body = {
+            'labels': {'cblabel': value.replace(' ', '_').lower()},
+            'labelFingerprint': self._gce_image.get('labelFingerprint'),
+        }
+        try:
+            (self._provider
+                 .gce_compute
+                 .images()
+                 .setLabels(project=self._provider.project_name,
+                            zone=self._provider.default_zone,
+                            image=self.name,
+                            body=request_body)
+                 .execute())
+        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()
+
     @property
     @property
     def description(self):
     def description(self):
         """
         """
@@ -827,18 +856,34 @@ class GCEInstance(BaseInstance):
         """
         """
         return self._gce_instance['name']
         return self._gce_instance['name']
 
 
-    @name.setter
+    @property
+    def label(self):
+        labels = self._gce_instance.get('labels')
+        return labels.get('cblabel', '') if labels else ''
+
+    @label.setter
     # pylint:disable=arguments-differ
     # pylint:disable=arguments-differ
-    def name(self, value):
-        """
-        Set the instance name.
-        """
-        GCEInstance.assert_valid_resource_name(value)
-        # In GCE, the name of the instance is provided by the client when
-        # initially creating the resource. The name cannot be changed after
-        # the instance is created.
-        cb.log.warning("Setting instance name after it is created is not "
-                       "supported by this provider: %s", value)
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        request_body = {
+            'labels': {'cblabel': value.replace(' ', '_').lower()},
+            'labelFingerprint': self._gce_instance.get('labelFingerprint'),
+        }
+        try:
+            (self._provider
+                 .gce_compute
+                 .instances()
+                 .setLabels(project=self._provider.project_name,
+                            zone=self._provider.default_zone,
+                            instance=self.name,
+                            body=request_body)
+                 .execute())
+        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()
 
 
     @property
     @property
     def public_ips(self):
     def public_ips(self):
@@ -895,6 +940,14 @@ class GCEInstance(BaseInstance):
         parsed_uri = self._provider.parse_url(machine_type_uri)
         parsed_uri = self._provider.parse_url(machine_type_uri)
         return GCEVMType(self._provider, parsed_uri.get_resource())
         return GCEVMType(self._provider, parsed_uri.get_resource())
 
 
+    @property
+    def subnet_id(self):
+        """
+        Get the zone for this instance.
+        """
+        return (self._gce_instance.get('networkInterfaces', [{}])[0]
+                .get('subnetwork'))
+
     def reboot(self):
     def reboot(self):
         """
         """
         Reboot this instance.
         Reboot this instance.
@@ -1000,12 +1053,14 @@ class GCEInstance(BaseInstance):
         return sg_ids
         return sg_ids
 
 
     @property
     @property
-    def key_pair_name(self):
+    def key_pair_id(self):
         """
         """
-        Get the name of the key pair associated with this instance.
+        Get the id of the key pair associated with this instance.
+        For GCE, since keys apply to all instances, return first
+        key in metadata.
         """
         """
         try:
         try:
-            return next(self._provider.security.key_pairs)
+            return next(iter(self._provider.security.key_pairs))
         except StopIteration:
         except StopIteration:
             return None
             return None
 
 
@@ -1019,11 +1074,12 @@ class GCEInstance(BaseInstance):
         self._inet_gateway = network.gateways.get_or_create_inet_gateway()
         self._inet_gateway = network.gateways.get_or_create_inet_gateway()
         return self._inet_gateway
         return self._inet_gateway
 
 
-    def create_image(self, name):
+    def create_image(self, label):
         """
         """
         Create a new image based on this instance.
         Create a new image based on this instance.
         """
         """
-        self.assert_valid_resource_name(name)
+        self.assert_valid_resource_label(label)
+        name = self._generate_name_from_label(label, 'cb-img')
         if 'disks' not in self._gce_instance:
         if 'disks' not in self._gce_instance:
             cb.log.error('Failed to create image: no disks found.')
             cb.log.error('Failed to create image: no disks found.')
             return
             return
@@ -1031,7 +1087,8 @@ class GCEInstance(BaseInstance):
             if 'boot' in disk and disk['boot']:
             if 'boot' in disk and disk['boot']:
                 image_body = {
                 image_body = {
                     'name': name,
                     'name': name,
-                    'sourceDisk': disk['source']
+                    'sourceDisk': disk['source'],
+                    'labels': {'cblabel': label.replace(' ', '_').lower()},
                 }
                 }
                 operation = (self._provider
                 operation = (self._provider
                              .gce_compute
                              .gce_compute
@@ -1302,6 +1359,53 @@ class GCENetwork(BaseNetwork):
     def name(self):
     def name(self):
         return self._network['name']
         return self._network['name']
 
 
+    @property
+    def label(self):
+        return self._network.get('description')
+
+    @label.setter
+    # pylint:disable=arguments-differ
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        body = {'description': value}
+        response = (self._provider
+                    .gce_compute
+                    .networks()
+                    .patch(project=self._provider.project_name,
+                           network=self.name,
+                           body=body)
+                    .execute())
+        self._provider.wait_for_operation(response)
+        self._network['description'] = value
+
+#     @property
+#     def label(self):
+#         labels = self._network.get('labels')
+#         return labels.get('cblabel', '') if labels else ''
+#
+#     @label.setter
+#     # pylint:disable=arguments-differ
+#     def label(self, value):
+#         request_body = {
+#             'labels': {'cblabel': value.replace(' ', '_').lower()},
+#             'labelFingerprint': self._network.get('labelFingerprint'),
+#         }
+#         try:
+#             (self._provider
+#                  .gce_compute
+#                  .networks()
+#                  .setLabels(project=self._provider.project_name,
+#                             zone=self._provider.default_zone,
+#                             resource=self.name,
+#                             body=request_body)
+#                  .execute())
+#         except Exception as e:
+#             cb.log.warning('Exception while setting network label: %s. '
+#                            'Check for invalid characters in label. '
+#                            'Should conform to RFC1035.', e)
+#             raise e
+#         self.refresh()
+
     @property
     @property
     def external(self):
     def external(self):
         """
         """
@@ -1346,9 +1450,9 @@ class GCENetwork(BaseNetwork):
             return False
             return False
         return True
         return True
 
 
-    def create_subnet(self, cidr_block, name=None, zone=None):
+    def create_subnet(self, label, cidr_block, zone):
         return self._provider.networking.subnets.create(
         return self._provider.networking.subnets.create(
-            self, cidr_block, name, zone)
+            label, self, cidr_block, zone)
 
 
     def refresh(self):
     def refresh(self):
         self._network = self._provider.get_resource('networks', self.id)
         self._network = self._provider.get_resource('networks', self.id)
@@ -1520,6 +1624,32 @@ class GCERouter(BaseRouter):
     def name(self):
     def name(self):
         return self._router['name']
         return self._router['name']
 
 
+    @property
+    def label(self):
+        return self._router.get('description')
+
+    @label.setter
+    # pylint:disable=arguments-differ
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        request_body = {
+            'description': value.replace(' ', '_').lower()
+        }
+        try:
+            (self._provider
+                 .gce_compute
+                 .routers()
+                 .patch(project=self._provider.project_name,
+                        router=self.name,
+                        body=request_body)
+                 .execute())
+        except Exception as e:
+            cb.log.warning('Exception while setting router label: %s. '
+                           'Check for invalid characters in label. '
+                           'Should conform to RFC1035.', e)
+            raise e
+        self.refresh()
+
     @property
     @property
     def region_name(self):
     def region_name(self):
         parsed_url = self._provider.parse_url(self.id)
         parsed_url = self._provider.parse_url(self.id)
@@ -1545,6 +1675,11 @@ class GCERouter(BaseRouter):
         network = parsed_url.get_resource()
         network = parsed_url.get_resource()
         return network['selfLink']
         return network['selfLink']
 
 
+    @property
+    def subnets(self):
+        network = self._provider.networking.networks.get(self.network_id)
+        return network.subnets
+
     def delete(self):
     def delete(self):
         response = (self._provider
         response = (self._provider
                         .gce_compute
                         .gce_compute
@@ -1651,12 +1786,32 @@ class GCESubnet(BaseSubnet):
     def name(self):
     def name(self):
         return self._subnet['name']
         return self._subnet['name']
 
 
-    @name.setter
-    def name(self, value):
-        GCESubnet.assert_valid_resource_name(value)
-        if value == self.name:
-            return
-        cb.log.warning('Cannot change the name of a GCE subnetwork')
+    @property
+    def label(self):
+        return self._subnet.get('description')
+
+    @label.setter
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        request_body = {
+            'description': value.replace(' ', '_').lower(),
+            'fingerprint': self._subnet.get('fingerprint')
+        }
+        try:
+            (self._provider
+                 .gce_compute
+                 .subnetworks()
+                 .patch(project=self._provider.project_name,
+                        region=self.region_name,
+                        subnetwork=self.name,
+                        body=request_body)
+                 .execute())
+        except Exception as e:
+            cb.log.warning('Exception while setting subnet label: %s. '
+                           'Check for invalid characters in label. '
+                           'Should conform to RFC1035.', e)
+            raise e
+        self.refresh()
 
 
     @property
     @property
     def cidr_block(self):
     def cidr_block(self):
@@ -1722,15 +1877,33 @@ class GCEVolume(BaseVolume):
         """
         """
         return self._volume.get('name')
         return self._volume.get('name')
 
 
-    @name.setter
-    # pylint:disable=arguments-differ
-    def name(self, value):
-        GCEVolume.assert_valid_resource_name(value)
-        # In GCE, the name of the volume is provided by the client when
-        # initially creating the resource. The name cannot be changed after
-        # the volume is created.
-        cb.log.warning("Setting volume name after it is created is not "
-                       "supported by this provider.")
+    @property
+    def label(self):
+        labels = self._volume.get('labels')
+        return labels.get('cblabel', '') if labels else ''
+
+    @label.setter
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        request_body = {
+            'labels': {'cblabel': value.replace(' ', '_').lower()},
+            'labelFingerprint': self._volume.get('labelFingerprint'),
+        }
+        try:
+            (self._provider
+                 .gce_compute
+                 .disks()
+                 .setLabels(project=self._provider.project_name,
+                            zone=self._provider.default_zone,
+                            resource=self.name,
+                            body=request_body)
+                 .execute())
+        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()
 
 
     @property
     @property
     def description(self):
     def description(self):
@@ -1856,12 +2029,12 @@ class GCEVolume(BaseVolume):
                          deviceName=device_name)
                          deviceName=device_name)
              .execute())
              .execute())
 
 
-    def create_snapshot(self, name, description=None):
+    def create_snapshot(self, label, description=None):
         """
         """
         Create a snapshot of this Volume.
         Create a snapshot of this Volume.
         """
         """
         return self._provider.storage.snapshots.create(
         return self._provider.storage.snapshots.create(
-            name, self, description)
+            label, self, description)
 
 
     def delete(self):
     def delete(self):
         """
         """
@@ -1916,15 +2089,33 @@ class GCESnapshot(BaseSnapshot):
         """
         """
         return self._snapshot.get('name')
         return self._snapshot.get('name')
 
 
-    @name.setter
+    @property
+    def label(self):
+        labels = self._snapshot.get('labels')
+        return labels.get('cblabel', '') if labels else ''
+
+    @label.setter
     # pylint:disable=arguments-differ
     # pylint:disable=arguments-differ
-    def name(self, value):
-        GCESnapshot.assert_valid_resource_name(value)
-        # In GCE, the name of the snapshot is provided by the client when
-        # initially creating the resource. The name cannot be changed after
-        # the snapshot is created.
-        cb.log.warning("Setting snapshot name after it is created is not "
-                       "supported by this provider.")
+    def label(self, value):
+        self.assert_valid_resource_label(value)
+        request_body = {
+            'labels': {'cblabel': value.replace(' ', '_').lower()},
+            'labelFingerprint': self._snapshot.get('labelFingerprint'),
+        }
+        try:
+            (self._provider
+                 .gce_compute
+                 .snapshots()
+                 .setLabels(project=self._provider.project_name,
+                            resource=self.name,
+                            body=request_body)
+                 .execute())
+        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()
 
 
     @property
     @property
     def description(self):
     def description(self):
@@ -2106,6 +2297,9 @@ class GCSObject(BaseBucketObject):
                                               expiration,
                                               expiration,
                                               url_encoded_signature))
                                               url_encoded_signature))
 
 
+    def refresh(self):
+        self._obj = self.bucket.objects.get(self.id)._obj
+
 
 
 class GCSBucketContainer(BaseBucketContainer):
 class GCSBucketContainer(BaseBucketContainer):
 
 

+ 59 - 42
cloudbridge/cloud/providers/gce/services.py

@@ -1,4 +1,5 @@
 import hashlib
 import hashlib
+import logging
 import time
 import time
 import uuid
 import uuid
 from collections import namedtuple
 from collections import namedtuple
@@ -8,7 +9,6 @@ import googleapiclient
 from retrying import retry
 from retrying import retry
 
 
 import cloudbridge as cb
 import cloudbridge as cb
-from cloudbridge.cloud.base.resources import BaseNetwork
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketService
 from cloudbridge.cloud.base.services import BaseBucketService
@@ -48,6 +48,8 @@ from .resources import GCEVMType
 from .resources import GCEVolume
 from .resources import GCEVolume
 from .resources import GCSBucket
 from .resources import GCSBucket
 
 
+log = logging.getLogger(__name__)
+
 
 
 class GCESecurityService(BaseSecurityService):
 class GCESecurityService(BaseSecurityService):
 
 
@@ -258,10 +260,11 @@ class GCEVMFirewallService(BaseVMFirewallService):
         return ClientPagedResultList(self.provider, vm_firewalls,
         return ClientPagedResultList(self.provider, vm_firewalls,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    def create(self, name, description, network_id=None):
-        GCEVMFirewall.assert_valid_resource_name(name)
-        network = self.provider.networking.networks.get(network_id)
-        fw = GCEVMFirewall(self._delegate, name, network, description)
+    def create(self, label, description, network=None):
+        GCEVMFirewall.assert_valid_resource_label(label)
+        network = (network if isinstance(network, GCENetwork)
+                   else self.provider.networking.networks.get(network))
+        fw = GCEVMFirewall(self._delegate, label, network, description)
         # This rule exists implicitly. Add it explicitly so that the firewall
         # This rule exists implicitly. Add it explicitly so that the firewall
         # is not empty and the rule is shown by list/get/find methods.
         # is not empty and the rule is shown by list/get/find methods.
         fw.rules.create_with_priority(
         fw.rules.create_with_priority(
@@ -712,7 +715,7 @@ class GCENetworkService(BaseNetworkService):
         return ClientPagedResultList(self.provider, networks,
         return ClientPagedResultList(self.provider, networks,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    def _create(self, name, cidr_block, create_subnetworks):
+    def _create(self, label, cidr_block, create_subnetworks):
         """
         """
         Possible values for 'create_subnetworks' are:
         Possible values for 'create_subnetworks' are:
 
 
@@ -729,10 +732,10 @@ class GCENetworkService(BaseNetworkService):
                            'in each region with explicit CIDR blocks',
                            'in each region with explicit CIDR blocks',
                            GCENetwork.DEFAULT_IPV4RANGE)
                            GCENetwork.DEFAULT_IPV4RANGE)
             cidr_block = None
             cidr_block = None
-        networks = self.list(filter='name eq %s' % name)
-        if len(networks) > 0:
-            return networks[0]
-        body = {'name': name}
+        name = GCENetwork._generate_name_from_label(label, 'cbnet')
+        body = {'name': name,
+                'labels': {'name': label}
+                }
         if cidr_block:
         if cidr_block:
             body['IPv4Range'] = cidr_block
             body['IPv4Range'] = cidr_block
         else:
         else:
@@ -753,13 +756,13 @@ class GCENetworkService(BaseNetworkService):
             cb.log.warning('googleapiclient.errors.HttpError: %s', http_error)
             cb.log.warning('googleapiclient.errors.HttpError: %s', http_error)
             return None
             return None
 
 
-    def create(self, name, cidr_block):
+    def create(self, label, cidr_block):
         """
         """
         Creates an auto mode VPC network with default subnets. It is possible
         Creates an auto mode VPC network with default subnets. It is possible
         to add additional subnets later.
         to add additional subnets later.
         """
         """
-        GCENetwork.assert_valid_resource_name(name)
-        return self._create(name, cidr_block, False)
+        GCENetwork.assert_valid_resource_label(label)
+        return self._create(label, cidr_block, False)
 
 
     def get_or_create_default(self):
     def get_or_create_default(self):
         return self._create(GCEFirewallsDelegate.DEFAULT_NETWORK, None, True)
         return self._create(GCEFirewallsDelegate.DEFAULT_NETWORK, None, True)
@@ -803,9 +806,11 @@ class GCERouterService(BaseRouterService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=routers)
                                      False, data=routers)
 
 
-    def create(self, name, network):
-        name = name if name else 'router-{0}'.format(uuid.uuid4())
-        GCERouter.assert_valid_resource_name(name)
+    def create(self, label, network):
+        log.debug("Creating GCE Router Service with params "
+                  "[label: %s network: %s]", label, network)
+        GCERouter.assert_valid_resource_label(label)
+        name = GCERouter._generate_name_from_label(label, 'cb-router')
 
 
         if not isinstance(network, GCENetwork):
         if not isinstance(network, GCENetwork):
             network = self.provider.networking.networks.get(network)
             network = self.provider.networking.networks.get(network)
@@ -818,7 +823,8 @@ class GCERouterService(BaseRouterService):
                             .insert(project=self.provider.project_name,
                             .insert(project=self.provider.project_name,
                                     region=region_name,
                                     region=region_name,
                                     body={'name': name,
                                     body={'name': name,
-                                          'network': network_url})
+                                          'network': network_url,
+                                          'description': label})
                             .execute())
                             .execute())
             if 'error' in response:
             if 'error' in response:
                 return None
                 return None
@@ -866,6 +872,8 @@ class GCESubnetService(BaseSubnetService):
         """
         """
         filter = None
         filter = None
         if network is not None:
         if network is not None:
+            network = (network if isinstance(network, GCENetwork)
+                       else self.provider.networking.networks.get(network))
             filter = 'network eq %s' % network.resource_url
             filter = 'network eq %s' % network.resource_url
         region_names = []
         region_names = []
         if zone:
         if zone:
@@ -887,36 +895,37 @@ class GCESubnetService(BaseSubnetService):
         return ClientPagedResultList(self.provider, subnets,
         return ClientPagedResultList(self.provider, subnets,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    def create(self, network, cidr_block, name=None, zone=None):
+    def create(self, label, network, cidr_block, zone):
         """
         """
-        GCE subnets are regional. The region is inferred from the zone if a
-        zone is provided; otherwise, the default region, as set in the
+        GCE subnets are regional. The region is inferred from the zone;
+        otherwise, the default region, as set in the
         provider, is used.
         provider, is used.
 
 
         If a subnet with overlapping IP range exists already, we return that
         If a subnet with overlapping IP range exists already, we return that
         instead of creating a new subnet. In this case, other parameters, i.e.
         instead of creating a new subnet. In this case, other parameters, i.e.
         the name and the zone, are ignored.
         the name and the zone, are ignored.
         """
         """
-        if not name:
-            name = 'subnet-{0}'.format(uuid.uuid4())
-        GCESubnet.assert_valid_resource_name(name)
+        GCESubnet.assert_valid_resource_label(label)
+        name = GCESubnet._generate_name_from_label(label, 'cbsubnet')
         region_name = self._zone_to_region_name(zone)
         region_name = self._zone_to_region_name(zone)
-        for subnet in self.iter(network=network):
-            if BaseNetwork.cidr_blocks_overlap(subnet.cidr_block, cidr_block):
-                if subnet.region_name != region_name:
-                    cb.log.error('Failed to create subnetwork in region %s: '
-                                 'the given IP range %s overlaps with a '
-                                 'subnetwork in a different region %s',
-                                 region_name, cidr_block, subnet.region_name)
-                    return None
-                return subnet
-            if subnet.name == name and subnet.region_name == region_name:
-                return subnet
+#         for subnet in self.iter(network=network):
+#            if BaseNetwork.cidr_blocks_overlap(subnet.cidr_block, cidr_block):
+#                 if subnet.region_name != region_name:
+#                     cb.log.error('Failed to create subnetwork in region %s: '
+#                                  'the given IP range %s overlaps with a '
+#                                  'subnetwork in a different region %s',
+#                                  region_name, cidr_block, subnet.region_name)
+#                     return None
+#                 return subnet
+#             if subnet.label == label and subnet.region_name == region_name:
+#                 return subnet
 
 
         body = {'ipCidrRange': cidr_block,
         body = {'ipCidrRange': cidr_block,
                 'name': name,
                 'name': name,
                 'network': network.resource_url,
                 'network': network.resource_url,
-                'region': region_name}
+                'region': region_name,
+                'labels': {'cblabel': label.replace(' ', '_').lower()}
+                }
         try:
         try:
             response = (self.provider
             response = (self.provider
                             .gce_compute
                             .gce_compute
@@ -1011,11 +1020,11 @@ class GCEVolumeService(BaseVolumeService):
         vol = self.provider.get_resource('disks', volume_id)
         vol = self.provider.get_resource('disks', volume_id)
         return GCEVolume(self.provider, vol) if vol else None
         return GCEVolume(self.provider, vol) if vol else None
 
 
-    def find(self, name, limit=None, marker=None):
+    def find(self, label, limit=None, marker=None):
         """
         """
         Searches for a volume by a given list of attributes.
         Searches for a volume by a given list of attributes.
         """
         """
-        filtr = 'name eq ' + name
+        filtr = 'label.cblabel eq ' + label
         max_result = limit if limit is not None and limit < 500 else 500
         max_result = limit if limit is not None and limit < 500 else 500
         response = (self.provider
         response = (self.provider
                         .gce_compute
                         .gce_compute
@@ -1063,7 +1072,7 @@ class GCEVolumeService(BaseVolumeService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=gce_vols)
                                      False, data=gce_vols)
 
 
-    def create(self, name, size, zone, snapshot=None, description=None):
+    def create(self, label, size, zone, snapshot=None, description=None):
         """
         """
         Creates a new volume.
         Creates a new volume.
 
 
@@ -1074,7 +1083,12 @@ class GCEVolumeService(BaseVolumeService):
         be a dash, lowercase letter, or digit, except the last character, which
         be a dash, lowercase letter, or digit, except the last character, which
         cannot be a dash.
         cannot be a dash.
         """
         """
-        GCEVolume.assert_valid_resource_name(name)
+        log.debug("Creating GCE Volume with parameters "
+                  "[label: %s size: %s zone: %s snapshot: %s "
+                  "description: %s]", label, size, zone, snapshot,
+                  description)
+        GCEVolume.assert_valid_resource_label(label)
+        name = GCEVolume._generate_name_from_label(label, 'cb-vol')
         if not isinstance(zone, GCEPlacementZone):
         if not isinstance(zone, GCEPlacementZone):
             zone = GCEPlacementZone(
             zone = GCEPlacementZone(
                 self.provider,
                 self.provider,
@@ -1088,6 +1102,7 @@ class GCEVolumeService(BaseVolumeService):
             'type': 'zones/{0}/diskTypes/{1}'.format(zone_name, 'pd-standard'),
             'type': 'zones/{0}/diskTypes/{1}'.format(zone_name, 'pd-standard'),
             'sourceSnapshot': snapshot_id,
             'sourceSnapshot': snapshot_id,
             'description': description,
             'description': description,
+            'labels': {'cblabel': label.replace(' ', '_').lower()}
         }
         }
         operation = (self.provider
         operation = (self.provider
                          .gce_compute
                          .gce_compute
@@ -1156,15 +1171,17 @@ class GCESnapshotService(BaseSnapshotService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=snapshots)
                                      False, data=snapshots)
 
 
-    def create(self, name, volume, description=None):
+    def create(self, label, volume, description=None):
         """
         """
         Creates a new snapshot of a given volume.
         Creates a new snapshot of a given volume.
         """
         """
-        GCESnapshot.assert_valid_resource_name(name)
+        GCESnapshot.assert_valid_resource_label(label)
+        name = GCESnapshot._generate_name_from_label(label, 'cbsnap')
         volume_name = volume.name if isinstance(volume, GCEVolume) else volume
         volume_name = volume.name if isinstance(volume, GCEVolume) else volume
         snapshot_body = {
         snapshot_body = {
             "name": name,
             "name": name,
-            "description": description
+            "description": description,
+            "labels": {"cblabel": label}
         }
         }
         operation = (self.provider
         operation = (self.provider
                          .gce_compute
                          .gce_compute