Starts a new instance with the given properties and returns
        the instance id.

        :param str key_name: name of the ssh key to connect
        :param str public_key_path: path to ssh public key
        :param str private_key_path: path to ssh private key
        :param str security_group: firewall rule definition to apply on the
                                   instance
        :param str flavor: machine type to use for the instance
        :param str image_id: image type (os) to use for the instance
        :param str image_userdata: command to execute after startup
        :param str username: username for the given ssh key, default None
        :param str node_name: name of the instance
        :param str tags: comma-separated list of "tags" to label the instance
        :param str scheduling: scheduling option to use for the instance ("preemptible")
        :param str|Sequence tags: "Tags" to label the instance.

        Can be either a single string (individual tags are comma-separated),
        or a sequence of strings (each string being a single tag).

        :return: str - instance id of the started instance

def start_instance(self,
                       # these are common to any
                       # CloudProvider.start_instance() call
                       key_name, public_key_path, private_key_path,
                       security_group, flavor, image_id, image_userdata,
                       username=None,
                       # these params are specific to the
                       # GoogleCloudProvider
                       node_name=None,
                       boot_disk_type='pd-standard',
                       boot_disk_size=10,
                       tags=None,
                       scheduling=None,
                       **kwargs):
        """Starts a new instance with the given properties and returns
        the instance id.

        :param str key_name: name of the ssh key to connect
        :param str public_key_path: path to ssh public key
        :param str private_key_path: path to ssh private key
        :param str security_group: firewall rule definition to apply on the
                                   instance
        :param str flavor: machine type to use for the instance
        :param str image_id: image type (os) to use for the instance
        :param str image_userdata: command to execute after startup
        :param str username: username for the given ssh key, default None
        :param str node_name: name of the instance
        :param str tags: comma-separated list of "tags" to label the instance
        :param str scheduling: scheduling option to use for the instance ("preemptible")
        :param str|Sequence tags: "Tags" to label the instance.

        Can be either a single string (individual tags are comma-separated),
        or a sequence of strings (each string being a single tag).

        :return: str - instance id of the started instance
        """
        # construct URLs
        project_url = '%s%s' % (GCE_URL, self._project_id)
        machine_type_url = '%s/zones/%s/machineTypes/%s' \
                           % (project_url, self._zone, flavor)
        boot_disk_type_url = '%s/zones/%s/diskTypes/%s' \
                           % (project_url, self._zone, boot_disk_type)
        # FIXME: `conf.py` should ensure that `boot_disk_size` has the right
        # type, so there would be no need to convert here
        boot_disk_size_gb = int(boot_disk_size)
        network_url = '%s/global/networks/%s' % (project_url, self._network)
        if image_id.startswith('http://') or image_id.startswith('https://'):
            image_url = image_id
        else:
            # The image names and full resource URLs for several Google-
            # provided images (debian, centos, etc.) follow a consistent
            # pattern, and so elasticluster supports a short-hand of just
            # an image name, such as
            #   "debian-7-wheezy-v20150526".
            # The cloud project in this case is then "debian-cloud".
            #
            # Several images do not follow this convention, and so are
            # special-cased here:
            #   backports-debian -> debian-cloud
            #   ubuntu           -> ubuntu-os-cloud
            #   containter-vm    -> google-containers
            if image_id.startswith('container-vm-'):
              os_cloud = 'google-containers'
            elif image_id.startswith('backports-debian-'):
              os_cloud = 'debian-cloud'
            elif image_id.startswith('ubuntu-'):
              os_cloud = 'ubuntu-os-cloud'
            else:
              os = image_id.split("-")[0]
              os_cloud = "%s-cloud" % os

            image_url = '%s%s/global/images/%s' % (
                GCE_URL, os_cloud, image_id)

        if scheduling is None:
            # use GCE's default
            scheduling_option = {}
        elif scheduling == 'preemptible':
            scheduling_option = {
              'preemptible': True
            }
        else:
            raise InstanceError("Unknown scheduling option: '%s'" % scheduling)

        if isinstance(tags, types.StringTypes):
            tags = tags.split(',')
        elif isinstance(tags, collections.Sequence):
            # ok, nothing to do
            pass
        elif tags is not None:
            raise TypeError(
                "The `tags` argument to `gce.start_instance`"
                " should be a string or a list, got {T} instead"
                .format(T=type(tags)))

        # construct the request body
        if node_name:
            instance_id = node_name.lower().replace('_', '-')  # GCE doesn't allow "_"
        else:
            instance_id = 'elasticluster-%s' % uuid.uuid4()

        with open(public_key_path, 'r') as f:
            public_key_content = f.read()

        instance = {
            'name': instance_id,
            'machineType': machine_type_url,
            'tags': {
              'items': tags,
            },
            'scheduling': scheduling_option,
            'disks': [{
                'autoDelete': 'true',
                'boot': 'true',
                'type': 'PERSISTENT',
                'initializeParams' : {
                    'diskName': "%s-disk" % instance_id,
                    'diskType': boot_disk_type_url,
                    'diskSizeGb': boot_disk_size_gb,
                    'sourceImage': image_url
                    }
                }],
            'networkInterfaces': [
                {'accessConfigs': [
                    {'type': 'ONE_TO_ONE_NAT',
                     'name': 'External NAT'
                    }],
                 'network': network_url
                }],
            'serviceAccounts': [
                {'email': self._email,
                 'scopes': GCE_DEFAULT_SCOPES
                }],
            "metadata": {
                "kind": "compute#metadata",
                "items": [
                    {
                        "key": "sshKeys",
                        "value": "%s:%s" % (username, public_key_content)
                    }
                ]
            }
        }

        # create the instance
        gce = self._connect()
        request = gce.instances().insert(
            project=self._project_id, body=instance, zone=self._zone)
        try:
            response = self._execute_request(request)
            response = self._wait_until_done(response)
            self._check_response(response)
            return instance_id
        except (HttpError, CloudProviderError) as e:
            log.error("Error creating instance `%s`" % e)
            raise InstanceError("Error creating instance `%s`" % e)