Ejemplo n.º 1
0
 def __init__(self, compute, project, region, zone):
     self.compute = compute
     self.project = project
     self.region = region
     self.zone = zone
     self.operation = Operations(self.compute, self.project, self.zone,
                                 self.region)
     self.autoscalers = []
     self.region_autoscalers = []
     self.unmanaged_instance_groups = []
     self.region_managed_instance_groups = []
     self.single_zone_managed_instance_groups = []
     self.instances = []
     self.instance_templates = []
     self.disks = []
     self.external_addresses = []
     self.target_pools = []
     self.target_instances = []
     self.healthcheck = []
     self.internal_backend_service = []
     self.global_backend_services = []
     self.regional_backend_services = []
     self.external_backend_service = []
     self.regional_forwarding_rules = []
     self.global_forwarding_rules = []
     self.urlmappings = []
     self.target_http_proxies = []
     self.target_tcp_proxies = []
     self.target_https_proxies = []
     self.target_ssl_proxies = []
     self.target_grpc_proxies = []
     self.networks = []
     self.subnetworks = []
     self.ssl_certificates = []
     self.possible_reserved_ips = []
Ejemplo n.º 2
0
    def __init__(self, compute, project, backend_service_name, network,
                 subnetwork, preserve_instance_external_ip, region):
        """ Initialization

        Args:
            compute: google compute engine
            project: project ID
            backend_service_name: name of the backend service
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the external IP
            region: region of the load balancer
        """
        super(RegionalBackendService, self).__init__(compute, project,
                                                     backend_service_name,
                                                     network, subnetwork,
                                                     preserve_instance_external_ip)
        self.region = region
        self.backend_service_configs = self.get_backend_service_configs()
        self.operations = Operations(self.compute, self.project, None,
                                     self.region)
        self.network_object = self.build_network_object()
        self.new_backend_service_configs = self.get_new_backend_config_with_new_network_info(
            self.backend_service_configs)
        self.log()
    def __init__(self, compute, project, instance_group_name, network_name,
                 subnetwork_name, preserve_instance_ip, zone):
        """ Initialize an unmanaged instance group object

        Args:
            compute: google compute engine
            project: project name
            network_name: target network
            subnetwork_name: target subnet
            instance_group_name: instance group's name
            preserve_instance_ip: whether to preserve instances external IPs
            zone: zone name of the instance group
        """
        super(UnmanagedInstanceGroup, self).__init__(compute, project,
                                                     instance_group_name,
                                                     network_name,
                                                     subnetwork_name,
                                                     preserve_instance_ip)
        self.zone = zone
        self.instance_selfLinks = self.list_instances()
        self.network = self.get_network()
        self.original_instance_group_configs = self.get_instance_group_configs()
        self.new_instance_group_configs = self.get_new_instance_group_configs_using_new_network(
            self.original_instance_group_configs)
        self.operation = Operations(self.compute, self.project, self.zone, None)
        self.selfLink = self.get_selfLink(self.original_instance_group_configs)
        self.log()
Ejemplo n.º 4
0
    def __init__(self,
                 compute,
                 project,
                 name,
                 zone,
                 network,
                 subnetwork,
                 preserve_instance_ip=False,
                 instance_configs=None):
        """ Initialize an instance object

        Args:
            compute: google compute engine
            project: project ID
            name: name of the instance
            region: region of the instance
            zone: zone of the instance
            instance_configs: the instance config
        """

        self.original_instance_configs = instance_configs or self.retrieve_instance_configs(
        )
        self.network_object = self.get_network()
        self.address_object = self.get_address()
        self.new_instance_configs = self.get_new_instance_configs()
        self.original_status = self.get_instance_status()
        self.operations = Operations(compute, project, zone)
        self.selfLink = self.get_selfLink(self.original_instance_configs)
        self.log()
Ejemplo n.º 5
0
 def __init__(self, compute, project, region, external_ip=None):
     """ Initialize an Address object
     Args:
         compute: google api compute engine
         project: project ID
         region: region of the instance
         external_ip: external IP address, such as "123.123.123.123"
     """
     self.operations = Operations(compute, project, None, region)
    def __init__(self, compute, project, instance_group_name, network_name,
                 subnetwork_name, preserve_instance_ip, region):
        """ Initialization


        Args:
            compute: google compute engine
            project: project ID
            instance_group_name: name of the instance group
            network_name: target network
            subnetwork_name: target subnet
            preserve_instance_ip: (only valid for unmanaged instance group) whether
                                    to preserve instances external IPs
        """
        super(RegionalManagedInstanceGroup,
              self).__init__(compute, project, instance_group_name,
                             network_name, subnetwork_name,
                             preserve_instance_ip)
        self.zone_or_region = region
        self.operation = Operations(self.compute, self.project, None, region)
        self.instance_group_manager_api = self.compute.regionInstanceGroupManagers(
        )
        self.autoscaler_api = self.compute.regionAutoscalers()
        self.is_multi_zone = True
        self.original_instance_group_configs = self.get_instance_group_configs(
        )
        self.new_instance_group_configs = deepcopy(
            self.original_instance_group_configs)
        self.autoscaler = self.get_autoscaler()
        self.autoscaler_configs = self.get_autoscaler_configs()
        self.selfLink = self.get_selfLink(self.original_instance_group_configs)
        self.log()
Ejemplo n.º 7
0
    def __init__(self, compute, project, instance_group_name, network_name,
                 subnetwork_name, preserve_instance_ip, zone):
        """ Initialization

        Args:
            compute: google compute engine
            project: project name
            network_name: target network
            subnetwork_name: target subnet
            instance_group_name: instance group's name
            preserve_instance_ip: whether to preserve instances external IPs
            zone: zone name of the instance group
        """
        super(ZonalManagedInstanceGroup,
              self).__init__(compute, project, instance_group_name,
                             network_name, subnetwork_name,
                             preserve_instance_ip)
        self.zone_or_region = zone
        self.operation = Operations(self.compute, self.project, zone, None)
        self.instance_group_manager_api = self.compute.instanceGroupManagers()
        self.autoscaler_api = self.compute.autoscalers()
        self.original_instance_group_configs = self.get_instance_group_configs(
        )
        self.new_instance_group_configs = deepcopy(
            self.original_instance_group_configs)
        self.autoscaler = self.get_autoscaler()
        self.autoscaler_configs = self.get_autoscaler_configs()
        self.selfLink = self.get_selfLink(self.original_instance_group_configs)
        self.log()
Ejemplo n.º 8
0
    def __init__(self, compute, project, forwarding_rule_name, network,
                 subnetwork):
        """ Initialization

        Args:
            compute: google compute engine
            project: project id
            forwarding_rule_name: the name of the forwarding rule
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the IPs of
                the instances serving the backend service
            region: region of the forwarding rule
        """
        super(GlobalForwardingRule,
              self).__init__(compute, project, forwarding_rule_name, network,
                             subnetwork)
        self.forwarding_rule_configs = self.get_forwarding_rule_configs()
        self.operations = Operations(self.compute, self.project)
        self.log()
Ejemplo n.º 9
0
    def __init__(self, compute, project, backend_service_name, network,
                 subnetwork, preserve_instance_external_ip):
        """ Initialization

        Args:
            compute: google compute engine
            project: project id
            backend_service_name: name of the backend service
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the external IPs
            of the instances serving the backend service
        """
        super(GlobalBackendService, self).__init__(compute, project,
                                                   backend_service_name,
                                                   network, subnetwork,
                                                   preserve_instance_external_ip)
        self.backend_service_configs = self.get_backend_service_configs()
        self.operations = Operations(self.compute, self.project)
        self.preserve_instance_external_ip = preserve_instance_external_ip
        self.log()
    def __init__(self, compute, project, instance_template_name, zone, region,
                 instance_template_body=None, network=None, subnetwork=None):
        """ Initialize an instance template object

        Args:
            compute: google compute engine
            project: project ID
            instance_template_name: name of the instance template
            zone: zone of the instance template
            region: region of the instance template
            instance_template_body: instance template's config
            network: target network
            subnetwork: target subnet
        """

        self.operation = Operations(self.compute, self.project, None, None)

        if self.instance_template_body == None:
            self.instance_template_body = self.get_instance_template_body()
        self.network_object = None
        if network != None:
            self.network_object = self.get_network()
    def __init__(self, compute, project, target_pool_name, region, network,
                 subnetwork, preserve_instance_external_ip):
        """ Initialization

        Args:
            compute: google compute engine
            project: project id
            target_pool_name: name of the target pool
            region: name of the region
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the external IPs
            of the instances serving the backends
        """

        self.target_pool_config = self.get_target_pool_configs()
        self.log()
        self.selfLink = self.get_selfLink()
        self.operations = Operations(self.compute, self.project, None,
                                     self.region)
        # The instances which don't belong to any instance groups
        self.attached_single_instances_selfLinks = []
        self.attached_managed_instance_groups_selfLinks = []
        self.get_attached_backends()
Ejemplo n.º 12
0
class GlobalBackendService(BackendService):
    def __init__(self, compute, project, backend_service_name, network,
                 subnetwork, preserve_instance_external_ip):
        """ Initialization

        Args:
            compute: google compute engine
            project: project id
            backend_service_name: name of the backend service
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the external IPs
            of the instances serving the backend service
        """
        super(GlobalBackendService, self).__init__(compute, project,
                                                   backend_service_name,
                                                   network, subnetwork,
                                                   preserve_instance_external_ip)
        self.backend_service_configs = self.get_backend_service_configs()
        self.operations = Operations(self.compute, self.project)
        self.preserve_instance_external_ip = preserve_instance_external_ip
        self.log()

    def get_backend_service_configs(self) -> dict:
        """ Get the config of the backend service

        Returns: config

        """
        args = {
            'project': self.project,
            'backendService': self.backend_service_name
        }
        return self.compute.backendServices().get(**args).execute()

    def detach_a_backend(self, backend_selfLink) -> dict:
        """ Detach a backend from the backend service

        Args:
            backend_configs: the backend to remove

        Returns: a deserialized Python object of the response

        """
        updated_backend_service = deepcopy(self.backend_service_configs)
        updated_backend_service['fingerprint'] = self.get_current_fingerprint()
        updated_backend_service['backends'] = [v for v in
                                               updated_backend_service[
                                                   'backends'] if
                                               not instance_group_links_is_equal(
                                                   v['group'],
                                                   backend_selfLink)]
        args = {
            'project': self.project,
            'backendService': self.backend_service_name,
            'body': updated_backend_service
        }
        detach_a_backend_operation = self.compute.backendServices().update(
            **args).execute()

        self.operations.wait_for_global_operation(
            detach_a_backend_operation['name'])
        print('Instance group %s has been detached.' % (backend_selfLink))
        return detach_a_backend_operation

    def reattach_all_backends(self) -> dict:
        """ Revert the backend service to its original backend config.
        If a backend has been detached, after this operation,
        it will be reattached to the backend service.

        Returns: a deserialized python object of the response

        """
        self.backend_service_configs[
            'fingerprint'] = self.get_current_fingerprint()
        args = {
            'project': self.project,
            'backendService': self.backend_service_name,
            'body': self.backend_service_configs
        }
        revert_backends_operation = self.compute.backendServices().update(
            **args).execute()
        self.operations.wait_for_global_operation(
            revert_backends_operation['name'])

        return revert_backends_operation

    def get_current_fingerprint(self) -> str:
        """ Get current fingerprint from the config

        Returns: fingerprint string

        """
        current_config = self.get_backend_service_configs()
        return current_config['fingerprint']

    def get_connecting_forwarding_rule_list(self):
        """ Get the configs of the forwarding rule which serves this backend service

        Returns: a deserialized python object of the response

        """
        forwarding_rule_list = []
        backend_service_selfLink = self.backend_service_configs['selfLink']

        request = self.compute.globalForwardingRules().list(
            project=self.project)
        while request is not None:
            response = request.execute()
            if 'items' not in response:
                break
            for forwarding_rule in response['items']:
                if 'backendService' in forwarding_rule and forwarding_rule[
                    'backendService'] == backend_service_selfLink:
                    forwarding_rule_list.append(forwarding_rule)
            request = self.compute.globalForwardingRules().list_next(
                previous_request=request,
                previous_response=response)
        return forwarding_rule_list

    def check_backend_health(self, backend_selfLink) -> bool:
        """ Check if the backends is healthy

        Args:
            backends_selfLink: url selfLink of the backends (just an instance group)

        Returns:

        """
        operation = self.compute.backendServices().getHealth(
            project=self.project,
            backendService=self.backend_service_name,
            body={
                "group": backend_selfLink
            }).execute()
        if 'healthStatus' not in operation:
            return False
        else:
            for instance_health_status in operation['healthStatus']:
                # If any instance in this backend becomes healthy,
                # this backend will start serving the backend service
                if 'healthState' in instance_health_status and \
                        instance_health_status['healthState'] == 'HEALTHY':
                    return True
        return False
class InstanceTemplate:
    @initializer
    def __init__(self, compute, project, instance_template_name, zone, region,
                 instance_template_body=None, network=None, subnetwork=None):
        """ Initialize an instance template object

        Args:
            compute: google compute engine
            project: project ID
            instance_template_name: name of the instance template
            zone: zone of the instance template
            region: region of the instance template
            instance_template_body: instance template's config
            network: target network
            subnetwork: target subnet
        """

        self.operation = Operations(self.compute, self.project, None, None)

        if self.instance_template_body == None:
            self.instance_template_body = self.get_instance_template_body()
        self.network_object = None
        if network != None:
            self.network_object = self.get_network()

    def get_instance_template_body(self) -> dict:
        """ Get the instance template's configs

        Returns: a deserialized object of the response

        """
        return self.compute.instanceTemplates().get(project=self.project,
                                                    instanceTemplate=self.instance_template_name).execute()

    def get_network(self) -> SubnetNetwork:
        """ Generate the network object

        Returns: a SubnetNetwork object

        """
        subnetwork_factory = SubnetNetworkHelper(self.compute, self.project,
                                                 self.zone, self.region)
        network = subnetwork_factory.generate_network(
            self.network,
            self.subnetwork)
        return network

    def insert(self) -> dict:
        """ Create the instance template

        Returns: a deserialized object of the response

        """
        insert_operation = self.compute.instanceTemplates().insert(
            project=self.project,
            body=self.instance_template_body).execute()
        self.operation.wait_for_global_operation(insert_operation['name'])
        return insert_operation

    def delete(self) -> dict:
        """ Delete the instance template

        Returns: a deserialized object of the response

        """
        delete_operation = self.compute.instanceTemplates().delete(
            project=self.project,
            instanceTemplate=self.instance_template_name).execute()

        self.operation.wait_for_global_operation(delete_operation['name'])
        return delete_operation

    def modify_instance_template_with_new_network(self, instance_template_body):
        """ Modify the instance template with the new network links

            Args:
                new_network_link: the selflink of the network
                new_subnetwork_link: the selflink of the subnetwork

        """
        instance_template_body['properties']['networkInterfaces'][0][
            'network'] = self.network_object.network_link
        instance_template_body['properties']['networkInterfaces'][0][
            'subnetwork'] = self.network_object.subnetwork_link
        # For testing
        # if add_network_metadata:
        #     if 'items' not in instance_template_body['properties'][
        #         'metadata']:
        #         instance_template_body['properties']['metadata'][
        #             'items'] = []
        #
        #     for item in instance_template_body['properties']['metadata'][
        #         'items']:
        #         if item['key'] == 'network':
        #             item['value'] = self.network_object.subnetwork_link
        #             return
        #
        #     instance_template_body['properties']['metadata'][
        #         'items'].append({
        #         'key': 'network',
        #         'value': self.network_object.subnetwork_link})

    def get_selfLink(self) -> str:
        """ Get the selfLink of the instance template

        Returns: selfLink

        """
        instance_template_body = self.get_instance_template_body()
        return instance_template_body['selfLink']

    def generate_random_name(self) -> str:
        """ Change the name of the instance template according to the current timestamp

        Returns: new name
        """
        new_name = self.instance_template_name[
                   0:25] + '-' + generate_timestamp_string()
        return new_name

    def generating_new_instance_template_using_network_info(self):
        """ Genereate a new InstanceTemplate object using the current network info

        Returns: an InstanceTemplate object

        """
        if self.network_object == None:
            return None
        else:
            new_instance_template_body = deepcopy(self.instance_template_body)
            self.modify_instance_template_with_new_network(
                new_instance_template_body)
            new_instance_template_name = self.generate_random_name()
            new_instance_template_body['name'] = new_instance_template_name
            new_instance_template = InstanceTemplate(self.compute, self.project,
                                                     new_instance_template_name,
                                                     self.zone, self.region,
                                                     new_instance_template_body)
            return new_instance_template

    def compare_original_network_and_target_network(self) -> bool:
        """ Check if the original network is the
        same as the target subnet

        Returns: True for the same
        """
        if self.network_object == None or self.network_object.subnetwork_link == None:
            raise InvalidTargetNetworkError

        if 'subnetwork' not in \
                self.instance_template_body['properties']['networkInterfaces'][
                    0]:
            return False
        elif is_equal_or_contians(
                self.instance_template_body['properties']['networkInterfaces'][
                    0]['subnetwork'],
                self.network_object.subnetwork_link):
            return True
        else:
            return False
Ejemplo n.º 14
0
class GoogleApiInterface:
    def __init__(self, compute, project, region, zone):
        self.compute = compute
        self.project = project
        self.region = region
        self.zone = zone
        self.operation = Operations(self.compute, self.project, self.zone,
                                    self.region)
        self.autoscalers = []
        self.region_autoscalers = []
        self.unmanaged_instance_groups = []
        self.region_managed_instance_groups = []
        self.single_zone_managed_instance_groups = []
        self.instances = []
        self.instance_templates = []
        self.disks = []
        self.external_addresses = []
        self.target_pools = []
        self.target_instances = []
        self.healthcheck = []
        self.internal_backend_service = []
        self.global_backend_services = []
        self.regional_backend_services = []
        self.external_backend_service = []
        self.regional_forwarding_rules = []
        self.global_forwarding_rules = []
        self.urlmappings = []
        self.target_http_proxies = []
        self.target_tcp_proxies = []
        self.target_https_proxies = []
        self.target_ssl_proxies = []
        self.target_grpc_proxies = []
        self.networks = []
        self.subnetworks = []
        self.ssl_certificates = []
        self.possible_reserved_ips = []

    def get_list_of_zones_from_regions(self):
        return self.compute.regions().get(
            project=self.project, region=self.region).execute()['zones']

    def create_unmanaged_instance_group_with_instances(self, configs,
                                                       instances):
        """ Create the instance group

        Returns: a deserialized object of the response

        """
        create_instance_group_operation = self.compute.instanceGroups().insert(
            project=self.project, zone=self.zone, body=configs).execute()
        self.unmanaged_instance_groups.append(configs['name'])
        self.operation.wait_for_zone_operation(
            create_instance_group_operation['name'])
        instance_links = []
        for instance in instances:
            instance_links.append(
                self.get_instance_configs(instance)['selfLink'])

        for instance_link in instance_links:
            insert_instance_operation = self.compute.instanceGroups(
            ).addInstances(project=self.project,
                           zone=self.zone,
                           instanceGroup=configs['name'],
                           body={
                               "instances": [{
                                   "instance": instance_link
                               }]
                           }).execute()
            self.operation.wait_for_zone_operation(
                insert_instance_operation['name'])
        return create_instance_group_operation

    def list_instances_in_unmanaged_instance_group(self, instance_group_name):
        operation = self.compute.instanceGroups().listInstances(
            project=self.project,
            zone=self.zone,
            instanceGroup=instance_group_name).execute()
        if 'items' not in operation:
            return []
        instance_configs = operation['items']
        instances = []
        for instance_configs in instance_configs:
            instances.append(instance_configs['instance'].split('/')[-1])
        return instances

    def get_unmanaged_instance_group_configs(self, instance_group_name):
        get_instance_group_operation = self.compute.instanceGroups().get(
            project=self.project,
            zone=self.zone,
            instanceGroup=instance_group_name).execute()
        return get_instance_group_operation

    def delete_unmanaged_instance_group(self, instance_group_name):
        delete_instance_group_operation = self.compute.instanceGroups().delete(
            project=self.project,
            zone=self.zone,
            instanceGroup=instance_group_name).execute()
        self.operation.wait_for_zone_operation(
            delete_instance_group_operation['name'])
        return delete_instance_group_operation

    def create_single_zone_managed_instance_group(self, configs):
        create_instance_group_operation = self.compute.instanceGroupManagers(
        ).insert(project=self.project, zone=self.zone, body=configs).execute()
        self.operation.wait_for_zone_operation(
            create_instance_group_operation['name'])
        self.single_zone_managed_instance_groups.append(configs['name'])

    def get_single_zone_managed_instance_group_configs(self,
                                                       instance_group_name):
        get_instance_group_operation = self.compute.instanceGroupManagers(
        ).get(project=self.project,
              zone=self.zone,
              instanceGroupManager=instance_group_name).execute()
        return get_instance_group_operation

    def delete_single_zone_managed_instance_group_configs(
            self, instance_group_name):
        delete_instance_group_operation = self.compute.instanceGroupManagers(
        ).delete(project=self.project,
                 zone=self.zone,
                 instanceGroupManager=instance_group_name).execute()
        self.operation.wait_for_zone_operation(
            delete_instance_group_operation['name'])
        return delete_instance_group_operation

    def create_multi_zone_managed_instance_group(self, configs):
        configs['distributionPolicy'] = {"zones": []}
        all_valid_zones = self.get_list_of_zones_from_regions()
        for zone in all_valid_zones:
            configs['distributionPolicy']['zones'].append({'zone': zone})
        create_instance_group_operation = self.compute.regionInstanceGroupManagers(
        ).insert(project=self.project, region=self.region,
                 body=configs).execute()
        self.operation.wait_for_region_operation(
            create_instance_group_operation['name'])
        self.region_managed_instance_groups.append(configs['name'])
        return create_instance_group_operation

    def get_multi_zone_managed_instance_group_configs(self,
                                                      instance_group_name):
        get_instance_group_operation = self.compute.regionInstanceGroupManagers(
        ).get(project=self.project,
              region=self.region,
              instanceGroupManager=instance_group_name).execute()
        return get_instance_group_operation

    def get_multi_zone_instance_template_configs(self, instance_group_name):
        instance_group_config = self.get_multi_zone_managed_instance_group_configs(
            instance_group_name)
        instance_template_name = \
            instance_group_config['instanceTemplate'].split('/')[-1]
        return self.get_instance_template_body(instance_template_name)

    def delete_multi_zone_managed_instance_group_configs(
            self, instance_group_name):
        delete_instance_group_operation = self.compute.regionInstanceGroupManagers(
        ).delete(project=self.project,
                 region=self.region,
                 instanceGroupManager=instance_group_name).execute()
        self.operation.wait_for_region_operation(
            delete_instance_group_operation['name'])
        return delete_instance_group_operation

    def create_instance(self,
                        instance_configs,
                        template_selfLink=None) -> dict:
        """ Create the instance using self.instance_template

            Returns:
                a deserialized object of the response

            Raises:
                googleapiclient.errors.HttpError: invalid request
        """
        if template_selfLink == None:
            create_instance_operation = self.compute.instances().insert(
                project=self.project, zone=self.zone,
                body=instance_configs).execute()
        else:
            create_instance_operation = self.compute.instances().insert(
                project=self.project,
                zone=self.zone,
                sourceInstanceTemplate=template_selfLink,
                body=instance_configs).execute()
        self.operation.wait_for_zone_operation(
            create_instance_operation['name'])
        self.instances.append(instance_configs['name'])
        external_ip = self.get_instance_external_ip(instance_configs['name'])
        self.possible_reserved_ips.append(external_ip)
        return create_instance_operation

    def get_instance_selfLink(self, instance_name):
        configs = self.compute.instances().get(
            project=self.project, zone=self.zone,
            instance=instance_name).execute()
        return configs['selfLink']

    def attach_disk(self, instance_name, disk_selfLink):
        operation = self.compute.instances().attachDisk(project=self.project,
                                                        zone=self.zone,
                                                        instance=instance_name,
                                                        body={
                                                            'source':
                                                            disk_selfLink
                                                        }).execute()

        self.operation.wait_for_zone_operation(operation['name'])
        return operation

    def delete_instance(self, instance_name) -> dict:
        delete_instance_operation = self.compute.instances().delete(
            project=self.project, zone=self.zone,
            instance=instance_name).execute()
        self.operation.wait_for_zone_operation(
            delete_instance_operation['name'])
        return delete_instance_operation

    def stop_instance(self, instance_name) -> dict:
        stop_instance_operation = self.compute.instances().stop(
            project=self.project, zone=self.zone,
            instance=instance_name).execute()
        self.operation.wait_for_zone_operation(stop_instance_operation['name'])
        return stop_instance_operation

    def get_instance_configs(self, instance_name):
        instance_template = self.compute.instances().get(
            project=self.project, zone=self.zone,
            instance=instance_name).execute()
        return instance_template

    def get_instance_external_ip(self, instance_name):
        configs = self.get_instance_configs(instance_name)
        try:
            return configs['networkInterfaces'][0]['accessConfigs'][0]['natIP']
        except:
            return None

    def get_instance_network_selfLink(self, instance_name):
        configs = self.get_instance_configs(instance_name)
        try:
            return configs['networkInterfaces'][0]['network']
        except:
            return None

    def get_regional_instance_group_network_selfLink(self,
                                                     instance_group_name):
        instance_template_name = \
            self.get_multi_zone_managed_instance_group_configs(
                instance_group_name)[
                'instanceTemplate'].split('/')[-1]
        return \
            self.get_instance_template_body(instance_template_name)[
                'properties'][
                'networkInterfaces'][0]['network']

    def create_disk(self, disk_config):
        create_disk_operation = self.compute.disks().insert(
            project=self.project, zone=self.zone, body=disk_config).execute()
        self.operation.wait_for_zone_operation(create_disk_operation['name'])
        self.disks.append(disk_config['name'])
        return create_disk_operation

    def delete_disk(self, disk_name):
        delete_disk_operation = self.compute.disks().delete(
            project=self.project, zone=self.zone, disk=disk_name).execute()
        self.operation.wait_for_zone_operation(delete_disk_operation['name'])
        return delete_disk_operation

    def create_autoscaler(self, configs):
        create_autoscaler_operation = self.compute.autoscalers().insert(
            project=self.project, zone=self.zone, body=configs).execute()
        self.operation.wait_for_zone_operation(
            create_autoscaler_operation['name'])
        self.autoscalers.append(configs['name'])
        return create_autoscaler_operation

    def get_autoscaler(self, autoscaler_name):
        return self.compute.autoscalers().get(
            project=self.project, zone=self.zone,
            autoscaler=autoscaler_name).execute()

    def get_region_autoscaler(self, autoscaler_name):
        return self.compute.regionAutoscalers().get(
            project=self.project,
            region=self.region,
            autoscaler=autoscaler_name).execute()

    def delete_autoscaler(self, autoscaler_name):
        delete_autoscaler_operation = self.compute.autoscalers().delete(
            project=self.project, zone=self.zone,
            autoscaler=autoscaler_name).execute()
        self.operation.wait_for_zone_operation(
            delete_autoscaler_operation['name'])
        return delete_autoscaler_operation

    def create_region_autoscaler(self, configs):
        create_autoscaler_operation = self.compute.regionAutoscalers().insert(
            project=self.project, region=self.region, body=configs).execute()
        self.operation.wait_for_region_operation(
            create_autoscaler_operation['name'])
        self.region_autoscalers.append(configs['name'])
        return create_autoscaler_operation

    def delete_region_autoscaler(self, autoscaler_name):
        delete_autoscaler_operation = self.compute.regionAutoscalers().delete(
            project=self.project,
            region=self.region,
            autoscaler=autoscaler_name).execute()
        self.operation.wait_for_region_operation(
            delete_autoscaler_operation['name'])
        return delete_autoscaler_operation

    def create_instance_template(self, instance_template_configs):
        create_instance_template_operation = self.compute.instanceTemplates(
        ).insert(project=self.project,
                 body=instance_template_configs).execute()
        self.operation.wait_for_global_operation(
            create_instance_template_operation['name'])
        self.instance_templates.append(instance_template_configs['name'])
        return create_instance_template_operation

    def delete_instance_template(self, instance_template_name):
        delete_instance_template_operation = self.compute.instanceTemplates(
        ).delete(project=self.project,
                 instanceTemplate=instance_template_name).execute()
        self.operation.wait_for_global_operation(
            delete_instance_template_operation['name'])

    def list_instance_template_names_begin_with_suffix(self, suffix):
        instance_template_name_list = []
        operation = self.compute.instanceTemplates().list(
            project=self.project).execute()
        if 'items' not in operation:
            return instance_template_name_list
        for instance_template in operation['items']:
            if instance_template['name'].startswith(suffix):
                instance_template_name_list.append(instance_template['name'])

        return instance_template_name_list

    def retrieve_instance_template_name(self, instance_zone_configs):
        instance_template_link = instance_zone_configs['instanceTemplate']
        return instance_template_link.split('/')[-1]

    def get_instance_template_body(self, instance_template_name) -> dict:
        """ Get the instance template's configs

        Returns: a deserialized object of the response

        """
        return self.compute.instanceTemplates().get(
            project=self.project,
            instanceTemplate=instance_template_name).execute()

    def insert_address(self, external_ip_address, address_name):
        operation = self.compute.addresses().insert(
            project=self.project,
            region=self.region,
            body=self.generate_external_ip_address_body(
                external_ip_address, address_name)).execute()
        self.operation.wait_for_region_operation(operation['name'])
        self.external_addresses.append(address_name)
        return operation

    def delete_address(self, external_ip_address_name):
        delete_operation = self.compute.addresses().delete(
            project=self.project,
            region=self.region,
            address=external_ip_address_name).execute()
        self.operation.wait_for_region_operation(delete_operation['name'])
        return delete_operation

    def generate_external_ip_address_body(self, external_ip, address_name):
        """Generate external IP address.

        Returns:
              {
              name: "ADDRESS_NAME",
              address: "IP_ADDRESS"
            }
        """
        external_ip_address_body = {}
        external_ip_address_body['name'] = address_name
        external_ip_address_body['address'] = external_ip
        return external_ip_address_body

    def create_target_pool(self, target_pool_configs):
        opertaion = self.compute.targetPools().insert(
            project=self.project, region=self.region,
            body=target_pool_configs).execute()
        self.operation.wait_for_region_operation(opertaion['name'])
        self.target_pools.append(target_pool_configs['name'])
        return opertaion

    def get_target_pool_config(self, target_pool_name):
        operation = self.compute.targetPools().get(
            project=self.project,
            region=self.region,
            targetPool=target_pool_name).execute()
        return operation

    def delete_a_target_pool(self, target_pool_name):
        operation = self.compute.targetPools().delete(
            project=self.project,
            region=self.region,
            targetPool=target_pool_name).execute()
        self.operation.wait_for_region_operation(operation['name'])
        return operation

    def create_target_instance(self, target_instance_configs):
        operation = self.compute.targetInstances().insert(
            project=self.project, zone=self.zone,
            body=target_instance_configs).execute()
        self.operation.wait_for_zone_operation(operation['name'])
        self.target_instances.append(target_instance_configs['name'])
        return operation

    def delete_target_instance(self, target_instance_name):
        operation = self.compute.targetInstances().delete(
            project=self.project,
            zone=self.zone,
            targetInstance=target_instance_name).execute()
        self.operation.wait_for_zone_operation(operation['name'])
        return operation

    def get_target_instance_configs(self, target_instance_name):
        operation = self.compute.targetInstances().get(
            project=self.project,
            zone=self.zone,
            targetInstance=target_instance_name).execute()
        return operation

    def add_instances_to_target_pool(self, target_pool_name,
                                     instance_selfLink):
        add_instance_body = {"instances": [{"instance": instance_selfLink}]}
        operation = self.compute.targetPools().addInstance(
            project=self.project,
            region=self.region,
            targetPool=target_pool_name,
            body=add_instance_body).execute()
        self.operation.wait_for_region_operation(operation['name'])
        return operation

    def get_instances_selfLink_list_from_target_pool(self, target_pool_name):
        operation = self.compute.targetPools().get(
            project=self.project,
            region=self.region,
            targetPool=target_pool_name).execute()
        return operation['instances']

    def regional_instance_group_set_target_pool(self, instance_group,
                                                target_pool_selfLink):
        """ Set the target pool of the managed instance group

        Args:
            target_pool_selfLink: selfLink of the target pool

        Returns: a deserialized Python object of the response

        """
        args = {
            'project': self.project,
            'instanceGroupManager': instance_group,
            'body': {
                "targetPools": [target_pool_selfLink]
            },
            'region': self.region
        }
        set_target_pool_operation = self.compute.regionInstanceGroupManagers(
        ).setTargetPools(**args).execute()

        self.operation.wait_for_region_operation(
            set_target_pool_operation['name'])

        return set_target_pool_operation

    def delete_all_firewalls(self):
        request = self.compute.firewalls().list(project=self.project)

        response = request.execute()
        if 'items' not in response:
            return
        for firewall in response['items']:
            # delete it

            if 'denied' in firewall:
                delete_operation = self.compute.firewalls().delete(
                    project=self.project, firewall=firewall['name']).execute()
                self.operation.wait_for_global_operation(
                    delete_operation['name'])

    def delete_all_firewalls_of_a_target_network(self, network_name):
        request = self.compute.firewalls().list(project=self.project)

        response = request.execute()
        if 'items' not in response:
            return
        for firewall in response['items']:
            # delete it
            if firewall['name'].startswith(network_name):
                delete_operation = self.compute.firewalls().delete(
                    project=self.project, firewall=firewall['name']).execute()
                self.operation.wait_for_global_operation(
                    delete_operation['name'])
                print('deleted firewall:', firewall['name'])

    def add_a_firewall(self, firewall_config):
        operation = self.compute.firewalls().insert(
            project=self.project, body=firewall_config).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def add_healthcheck(self, healthcheck_configs):
        operation = self.compute.healthChecks().insert(
            project=self.project, body=healthcheck_configs).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.healthcheck.append(healthcheck_configs['name'])
        return operation

    def get_healthcheck(self, healthcheck_name):
        operation = self.compute.healthChecks().get(
            project=self.project, healthCheck=healthcheck_name).execute()
        return operation

    def delete_healthcheck(self, healthcheck_name):
        operation = self.compute.healthChecks().delete(
            project=self.project, healthCheck=healthcheck_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def create_internal_backend_service(self, backend_service_configs):
        operation = self.compute.regionBackendServices().insert(
            project=self.project,
            region=self.region,
            body=backend_service_configs).execute()

        self.operation.wait_for_region_operation(operation['name'])
        self.internal_backend_service.append(backend_service_configs['name'])
        return operation

    def create_regional_backend_service(self, backend_service_configs):
        operation = self.compute.regionBackendServices().insert(
            project=self.project,
            region=self.region,
            body=backend_service_configs).execute()

        self.operation.wait_for_region_operation(operation['name'])
        self.regional_backend_services.append(backend_service_configs['name'])
        return operation

    def get_backends_links_from_backend_service_configs(
            self, backend_service_configs):
        if 'backends' not in backend_service_configs:
            return []
        backends = backend_service_configs['backends']
        backends_links = []
        for backend in backends:
            backends_links.append(backend['group'])
        return backends_links

    def delete_internal_backend_service(self, backend_service_name):

        operation = self.compute.regionBackendServices().delete(
            project=self.project,
            region=self.region,
            backendService=backend_service_name).execute()

        self.operation.wait_for_region_operation(operation['name'])
        return operation

    def delete_regional_backend_service(self, backend_service_name):

        operation = self.compute.regionBackendServices().delete(
            project=self.project,
            region=self.region,
            backendService=backend_service_name).execute()

        self.operation.wait_for_region_operation(operation['name'])
        return operation

    def create_external_backend_service(self, backend_service_configs):
        operation = self.compute.backendServices().insert(
            project=self.project, body=backend_service_configs).execute()

        self.operation.wait_for_global_operation(operation['name'])
        self.external_backend_service.append(backend_service_configs['name'])
        return operation

    def create_global_backend_service(self, backend_service_configs):
        operation = self.compute.backendServices().insert(
            project=self.project, body=backend_service_configs).execute()

        self.operation.wait_for_global_operation(operation['name'])
        self.global_backend_services.append(backend_service_configs['name'])
        return operation

    def delete_external_backend_service(self, backend_service_name):
        operation = self.compute.backendServices().delete(
            project=self.project,
            backendService=backend_service_name).execute()
        print('deleting backend service')
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def delete_global_backend_service(self, backend_service_name):
        operation = self.compute.backendServices().delete(
            project=self.project,
            backendService=backend_service_name).execute()
        print('deleting backend service')
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def get_internal_backend_service_configs(self, backend_service_name):
        return self.compute.regionBackendServices().get(
            project=self.project,
            region=self.region,
            backendService=backend_service_name).execute()

    def get_regional_backend_service_configs(self, backend_service_name):
        return self.compute.regionBackendServices().get(
            project=self.project,
            region=self.region,
            backendService=backend_service_name).execute()

    def get_external_backend_service_configs(self, backend_service_name):
        return self.compute.backendServices().get(
            project=self.project,
            backendService=backend_service_name).execute()

    def get_global_backend_service_configs(self, backend_service_name):
        return self.compute.backendServices().get(
            project=self.project,
            backendService=backend_service_name).execute()

    def create_regional_forwarding_rule(self, forwarding_rule_configs):
        operation = self.compute.forwardingRules().insert(
            project=self.project,
            region=self.region,
            body=forwarding_rule_configs).execute()
        self.operation.wait_for_region_operation(operation['name'])
        self.regional_forwarding_rules.append(forwarding_rule_configs['name'])
        return operation

    def delete_regional_forwarding_rule(self, forwarding_rule_name):
        operation = self.compute.forwardingRules().delete(
            project=self.project,
            region=self.region,
            forwardingRule=forwarding_rule_name).execute()
        self.operation.wait_for_region_operation(operation['name'])

        return operation

    def get_regional_forwarding_rule_config(self, forwarding_rule_name):
        return self.compute.forwardingRules().get(
            project=self.project,
            region=self.region,
            forwardingRule=forwarding_rule_name).execute()

    def create_global_forwarding_rule(self, forwarding_rule_configs):
        operation = self.compute.globalForwardingRules().insert(
            project=self.project, body=forwarding_rule_configs).execute()
        print('waiting for forwarding rule creation')
        self.operation.wait_for_global_operation(operation['name'])
        self.global_forwarding_rules.append(forwarding_rule_configs['name'])
        return operation

    def delete_global_forwarding_rule(self, forwarding_rule_name):
        operation = self.compute.globalForwardingRules().delete(
            project=self.project,
            forwardingRule=forwarding_rule_name).execute()
        self.operation.wait_for_global_operation(operation['name'])

        return operation

    def get_global_forwarding_rule_config(self, forwarding_rule_name):
        return self.compute.globalForwardingRules().get(
            project=self.project,
            forwardingRule=forwarding_rule_name).execute()

    def create_urlmapping(self, urlmapping_configs):
        operation = self.compute.urlMaps().insert(
            project=self.project, body=urlmapping_configs).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.urlmappings.append(urlmapping_configs['name'])
        return operation

    def delete_urlmapping(self, urlmapping_name):
        operation = self.compute.urlMaps().delete(
            project=self.project, urlMap=urlmapping_name).execute()
        print(operation)
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def create_http_proxy(self, http_proxy_name, urlmapping_selfLink):
        body = {"name": http_proxy_name, "urlMap": urlmapping_selfLink}
        operation = self.compute.targetHttpProxies().insert(
            project=self.project, body=body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.target_http_proxies.append(http_proxy_name)
        return operation

    def create_tcp_proxy(self, tcp_proxy_name, backend_service_selfLink):
        body = {
            "description": "",
            "name": tcp_proxy_name,
            "proxyHeader": "NONE",
            "service": backend_service_selfLink
        }
        operation = self.compute.targetTcpProxies().insert(
            project=self.project, body=body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.target_tcp_proxies.append(tcp_proxy_name)
        return operation

    def create_ssl_proxy(self, proxy_name, backend_service_selfLink,
                         ssl_certificate_selfLink):
        body = {
            "name": proxy_name,
            "proxyHeader": "NONE",
            "service": backend_service_selfLink,
            "sslCertificates": [ssl_certificate_selfLink]
        }
        operation = self.compute.targetSslProxies().insert(
            project=self.project, body=body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.target_ssl_proxies.append(proxy_name)
        return operation

    def create_grpc_proxy(self, proxy_name, urlmap_selfLink):
        body = {
            "name": proxy_name,
            "urlMap": urlmap_selfLink,
            "validateForProxyless": False
        }
        operation = self.compute.targetGrpcProxies().insert(
            project=self.project, body=body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.target_grpc_proxies.append(proxy_name)
        return operation

    def create_ssl_certificate(self, name):
        body = {
            "name": name,
            "managed": {
                "domains": ["www.example.com"],
                "domainStatus": {
                    "www.example.com": "FAILED_NOT_VISIBLE"
                }
            },
            "type": "MANAGED"
        }
        operation = self.compute.sslCertificates().insert(project=self.project,
                                                          body=body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.ssl_certificates.append(name)
        return operation

    def delete_ssl_certificate(self, name):
        operation = self.compute.sslCertificates().delete(
            project=self.project, sslCertificate=name).execute()
        self.operation.wait_for_global_operation(operation['name'])

        return operation

    def create_https_proxy(self, https_proxy_name, urlmapping_selfLink,
                           certificate_selfLink):
        body = {
            "name": https_proxy_name,
            "urlMap": urlmapping_selfLink,
            "sslCertificates": [certificate_selfLink],
            "quicOverride": "NONE",
        }
        operation = self.compute.targetHttpsProxies().insert(
            project=self.project, body=body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.target_https_proxies.append(https_proxy_name)
        return operation

    def delete_http_proxy(self, http_proxy_name):
        operation = self.compute.targetHttpProxies().delete(
            project=self.project, targetHttpProxy=http_proxy_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def delete_tcp_proxy(self, tcp_proxy_name):
        operation = self.compute.targetTcpProxies().delete(
            project=self.project, targetTcpProxy=tcp_proxy_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def delete_ssl_proxy(self, ssl_proxy_name):
        operation = self.compute.targetSslProxies().delete(
            project=self.project, targetSslProxy=ssl_proxy_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def delete_https_proxy(self, https_proxy_name):
        operation = self.compute.targetHttpsProxies().delete(
            project=self.project, targetHttpsProxy=https_proxy_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def delete_grpc_proxy(self, proxy_name):
        operation = self.compute.targetGrpcProxies().delete(
            project=self.project, targetGrpcProxy=proxy_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.target_grpc_proxies.append(proxy_name)
        return operation

    def create_legacy_network(self, network_name):
        network_body = {
            "name": network_name,
            "IPv4Range": "10.240.0.0/16",
            "routingConfig": {
                "routingMode": "REGIONAL"
            }
        }

        operation = self.compute.networks().insert(
            project=self.project, body=network_body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.networks.append(network_name)
        return operation

    def get_network(self, network_name):

        operation = self.compute.networks().get(
            project=self.project, network=network_name).execute()
        return operation

    def delete_network(self, network_name):

        operation = self.compute.networks().delete(
            project=self.project, network=network_name).execute()
        self.operation.wait_for_global_operation(operation['name'])
        return operation

    def create_auto_subnetwork(self, network_name):
        network_body = {
            "name": network_name,
            "autoCreateSubnetworks": True,
            "routingConfig": {
                "routingMode": "REGIONAL"
            },
        }
        operation = self.compute.networks().insert(
            project=self.project, body=network_body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.networks.append(network_name)
        return operation

    def delete_subnetwork(self, subnetwork_name):
        operation = self.compute.subnetworks().delete(
            project=self.project,
            region=self.region,
            subnetwork=subnetwork_name).execute()
        self.operation.wait_for_region_operation(operation['name'])
        return operation

    def get_subnetwork(self, subnetwork_name):
        operation = self.compute.subnetworks().get(
            project=self.project,
            region=self.region,
            subnetwork=subnetwork_name).execute()
        return operation

    def create_non_auto_network(self, network_name):
        network_body = {
            "name": network_name,
            "autoCreateSubnetworks": False,
            "routingConfig": {
                "routingMode": "REGIONAL"
            },
        }

        operation = self.compute.networks().insert(
            project=self.project, body=network_body).execute()
        self.operation.wait_for_global_operation(operation['name'])
        self.networks.append(network_name)
        return operation['targetLink']

    def create_subnetwork_using_random_ip_range(self, subnetwork_name,
                                                network_selfLink):
        import random

        MAX_FAIL_TIME = 5
        for i in range(MAX_FAIL_TIME):
            try:
                random_ipCidrRange = '10.' + str(random.randint(
                    1, 120)) + '.0.0/24'
                return self.create_subnetwork(subnetwork_name,
                                              network_selfLink,
                                              random_ipCidrRange)
            except:
                continue
        return None

    def create_subnetwork(self,
                          subnetwork_name,
                          network_selfLink,
                          subnetwork_ipCidrRange='10.120.0.0/24'):
        subnetwork_body = {
            "name": subnetwork_name,
            "network": network_selfLink,
            "ipCidrRange": subnetwork_ipCidrRange,
            "privateIpGoogleAccess": False,
            "purpose": "PRIVATE"
        }

        operation = self.compute.subnetworks().insert(
            project=self.project, region=self.region,
            body=subnetwork_body).execute()

        self.operation.wait_for_region_operation(operation['name'])
        self.subnetworks.append(subnetwork_name)
        return operation

    def get_project_selfLink(self):
        return self.compute.projects().get(
            project=self.project).execute()['selfLink']

    def delete_reserved_ips(self, ipv4_address_list):
        address_list = self.compute.addresses().list(
            project=self.project, region=self.region).execute()
        if 'items' not in address_list:
            return
        for address in address_list['items']:
            if address['address'] in ipv4_address_list and address[
                    'status'] == 'RESERVED':
                try:
                    self.delete_address(address['name'])
                except Exception as e:
                    print(str(e))
                    continue

    def clean_all_resources(self):
        # get all the instance templates created during the test
        instance_templates_created_during_migration = []
        for instance_template_name in self.instance_templates:
            instance_templates_created_during_migration.extend(
                self.list_instance_template_names_begin_with_suffix(
                    instance_template_name[:20]))
        self.instance_templates.extend(
            instance_templates_created_during_migration)
        self.instance_templates = list(set(self.instance_templates))
        print('Cleaning all test resources')
        print('Deleting forwarding rules')
        for forwarding_rule in self.regional_forwarding_rules:
            try:
                self.delete_regional_forwarding_rule(forwarding_rule)
            except:
                continue
        for forwarding_rule in self.global_forwarding_rules:
            try:
                self.delete_global_forwarding_rule(forwarding_rule)
            except:
                continue
        print('Deleting backend services')

        for backend_service in self.internal_backend_service:
            try:
                self.delete_internal_backend_service(backend_service)
            except:
                continue
        print('Deleting target proxies')
        for proxy in self.target_http_proxies:
            try:
                self.delete_http_proxy(proxy)
            except Exception as e:
                print('Delete target proxy failed: ', str(e))
                continue
        for proxy in self.target_https_proxies:
            try:
                self.delete_https_proxy(proxy)
            except:
                continue
        for proxy in self.target_tcp_proxies:
            try:
                self.delete_tcp_proxy(proxy)
            except:
                continue

        for proxy in self.target_ssl_proxies:
            try:
                self.delete_ssl_proxy(proxy)
            except:
                continue

        for proxy in self.target_grpc_proxies:
            try:
                self.delete_grpc_proxy(proxy)
            except:
                continue

        print('Deleting url mappings:', self.urlmappings)
        for urlmapping in self.urlmappings:
            try:
                self.delete_urlmapping(urlmapping)
            except Exception as e:
                continue
        print('Deleting external backend services')
        for backend_service in self.external_backend_service:
            try:
                self.delete_external_backend_service(backend_service)
            except Exception as e:
                continue
        print('Deleting regional backend services')
        for backend_service in self.regional_backend_services:
            try:
                self.delete_regional_backend_service(backend_service)
            except Exception as e:
                continue
        print('Deleting global backend services')
        for backend_service in self.global_backend_services:
            try:
                self.delete_global_backend_service(backend_service)
            except Exception as e:
                continue
        print('Deleting target instances')
        for target_instance in self.target_instances:
            try:
                self.delete_target_instance(target_instance)
            except:
                continue
        print('Deleting target pools')
        for target_pool in self.target_pools:
            try:
                self.delete_a_target_pool(target_pool)
            except:
                continue
        print('Deleting auto scalers')
        for autoscaler in self.autoscalers:
            try:
                self.delete_autoscaler(autoscaler)
            except:
                continue
        for region_autoscaler in self.region_autoscalers:
            try:
                self.delete_region_autoscaler(region_autoscaler)
            except:
                continue
        print('Deleting instance groups')
        for unmanged_instance_group in self.unmanaged_instance_groups:
            try:
                self.delete_unmanaged_instance_group(unmanged_instance_group)
            except:
                continue
        for region_managed_instance_group in self.region_managed_instance_groups:
            try:
                self.delete_multi_zone_managed_instance_group_configs(
                    region_managed_instance_group)
            except:
                continue
        for single_zone_managed_instance_group in self.single_zone_managed_instance_groups:
            try:
                self.delete_single_zone_managed_instance_group_configs(
                    single_zone_managed_instance_group)
            except:
                continue
        print('Deleting instances')
        for instance in self.instances:
            try:
                self.delete_instance(instance)
            except:
                continue
        print('Deleting disks')
        for disk in self.disks:
            try:
                self.delete_disk(disk)
            except:
                continue
        print('Deleting instance templates')
        for instance_template in self.instance_templates:
            try:
                self.delete_instance_template(instance_template)
            except:
                continue
        print('Deleting static external IPs')
        for address_name in self.external_addresses:
            try:
                self.delete_address(address_name)
            except:
                continue

        self.delete_reserved_ips(self.possible_reserved_ips)

        print('Deleting health checks')
        for healthcheck in self.healthcheck:
            try:
                self.delete_healthcheck(healthcheck)
            except:
                continue
        print('Clean firewalls')
        for network in self.networks:
            try:
                self.delete_all_firewalls_of_a_target_network(network)
            except:
                continue

        for ssl_certificate in self.ssl_certificates:
            try:
                self.delete_ssl_certificate(ssl_certificate)
            except:
                continue

        print('Deleting subnetworks')

        for network in self.subnetworks:
            try:
                self.delete_all_firewalls_of_a_target_network(network)
                self.delete_subnetwork(network)
            except:
                continue

        print('Deleting networks')
        for network in self.networks:
            try:
                self.delete_all_firewalls_of_a_target_network(network)
                self.delete_network(network)
            except:
                continue
class UnmanagedInstanceGroup(InstanceGroup):
    def __init__(self, compute, project, instance_group_name, network_name,
                 subnetwork_name, preserve_instance_ip, zone):
        """ Initialize an unmanaged instance group object

        Args:
            compute: google compute engine
            project: project name
            network_name: target network
            subnetwork_name: target subnet
            instance_group_name: instance group's name
            preserve_instance_ip: whether to preserve instances external IPs
            zone: zone name of the instance group
        """
        super(UnmanagedInstanceGroup, self).__init__(compute, project,
                                                     instance_group_name,
                                                     network_name,
                                                     subnetwork_name,
                                                     preserve_instance_ip)
        self.zone = zone
        self.instance_selfLinks = self.list_instances()
        self.network = self.get_network()
        self.original_instance_group_configs = self.get_instance_group_configs()
        self.new_instance_group_configs = self.get_new_instance_group_configs_using_new_network(
            self.original_instance_group_configs)
        self.operation = Operations(self.compute, self.project, self.zone, None)
        self.selfLink = self.get_selfLink(self.original_instance_group_configs)
        self.log()

    def get_network(self) -> SubnetNetwork:
        """ Get a SubnetNetwork object

        Returns:

        """
        print('Checking the target network information.')
        subnetwork_factory = SubnetNetworkHelper(self.compute, self.project,
                                                 self.zone)
        network = subnetwork_factory.generate_network(
            self.network_name,
            self.subnetwork_name)
        return network

    def get_instance_group_configs(self) -> dict:
        """ Get instance group's configurations

        Returns: instance group's configurations

        """
        return self.compute.instanceGroups().get(project=self.project,
                                                 zone=self.zone,
                                                 instanceGroup=self.instance_group_name).execute()

    def list_instances(self) -> list:
        """Retrieve all the instances in this instance group,

        Returns: a list of the instances' selfLinks

        """
        instance_selfLinks = []
        request = self.compute.instanceGroups().listInstances(
            project=self.project, zone=self.zone,
            instanceGroup=self.instance_group_name)
        while request is not None:
            response = request.execute()
            # no instances in the instance group
            if 'items' not in response:
                break
            for instance_with_named_ports in response['items']:
                print(instance_with_named_ports)
                instance_selfLinks.append(
                    instance_with_named_ports['instance'])
            request = self.compute.instanceGroups().listInstances_next(
                previous_request=request, previous_response=response)
        return instance_selfLinks

    def delete_instance_group(self) -> dict:
        """ Delete the instance group

        Returns:  a deserialized object of the response

        """

        delete_instance_group_operation = self.compute.instanceGroups().delete(
            project=self.project,
            zone=self.zone,
            instanceGroup=self.instance_group_name).execute()
        self.operation.wait_for_zone_operation(
            delete_instance_group_operation['name'])
        return delete_instance_group_operation

    def create_instance_group(self, configs) -> dict:
        """ Create the instance group

        Returns: a deserialized object of the response

        """
        create_instance_group_operation = self.compute.instanceGroups().insert(
            project=self.project,
            zone=self.zone,
            body=configs).execute()
        self.operation.wait_for_zone_operation(
            create_instance_group_operation['name'])
        return create_instance_group_operation

    def add_an_instance(self, instance_selfLink):
        """ Add an instance into the instance group

        Args:
            instance_selflink: the instance's selfLink

        Returns: a deserialized object of the response
        Raises: HttpError

        """
        try:
            add_instance_operation = self.compute.instanceGroups().addInstances(
                project=self.project,
                zone=self.zone,
                instanceGroup=self.instance_group_name,
                body={
                    'instances': [{
                        'instance': instance_selfLink}]}).execute()
            self.operation.wait_for_zone_operation(
                add_instance_operation['name'])
            return add_instance_operation
        except HttpError as e:
            error_reason = e._get_reason()
            if 'already a member of' in error_reason:
                warnings.warn(error_reason, Warning)
            else:
                raise e

    def remove_an_instance(self, instance_selfLink):
        """ Remove an instance from the instance group

         Args:
             instance_selflink: the instance to be removed

         Returns: a deserialized object of the response
         Raises: HttpError

         """
        try:
            add_instance_operation = self.compute.instanceGroups().removeInstances(
                project=self.project,
                zone=self.zone,
                instanceGroup=self.instance_group_name,
                body={
                    'instances': [{
                        'instance': instance_selfLink}]}).execute()
            self.operation.wait_for_zone_operation(
                add_instance_operation['name'])
            return add_instance_operation
        except HttpError as e:
            error_reason = e._get_reason()
            if 'is not a member of' in error_reason:
                warnings.warn(error_reason, Warning)
            else:
                raise e

    def add_all_instances(self):
        """ Add all the instances in instances to the current instance group

        """
        for instance_selfLink in self.instance_selfLinks:
            try:
                self.add_an_instance(instance_selfLink)
            except HttpError:
                raise AddInstanceToInstanceGroupError(
                    'Failed to add all instances to the instance group.')

    def get_new_instance_group_configs_using_new_network(self,
                                                         instance_group_configs):
        """ Modify the instance group configs with self.network

        Args:
            instance_group_configs: configs of the instance group

        Returns:

        """
        new_instance_group_configs = deepcopy(instance_group_configs)
        new_instance_group_configs['network'] = self.network.network_link
        new_instance_group_configs['subnetwork'] = self.network.subnetwork_link
        return new_instance_group_configs

    def compare_original_network_and_target_network(self) -> bool:
        """ check if the original network is the
        same as the target subnet

        Returns: True/False
        """
        if 'subnetwork' not in self.original_instance_group_configs:
            return False
        elif is_equal_or_contians(
                self.original_instance_group_configs['subnetwork'],
                self.network.subnetwork_link):
            return True
        else:
            return False
Ejemplo n.º 16
0
class Address:
    @initializer
    def __init__(self, compute, project, region, external_ip=None):
        """ Initialize an Address object
        Args:
            compute: google api compute engine
            project: project ID
            region: region of the instance
            external_ip: external IP address, such as "123.123.123.123"
        """
        self.operations = Operations(compute, project, None, region)

    def get_region(self) -> str:
        """ Get region information

            Returns: region name

            Raises:
                googleapiclient.errors.HttpError: invalid request
        """
        return self.compute.zones().get(
            project=self.project,
            zone=self.zone).execute()['region'].split('regions/')[1]

    def retrieve_ip_from_network_interface(self, network_interface):
        """ Get external IP address from the network interface dict
        and update self.external_ip

        Args:
            network_interface: the network interface dictionary, such as
            {
              "network": "https://www.googleapis.com/compute/v1/projects/mock_project/global/networks/default",
              "networkIP": "10.128.0.9",
              "accessConfigs": [
                {
                  "type": "ONE_TO_ONE_NAT",
                  "name": "External NAT",
                  "natIP": "23.24.5.64",
                  "networkTier": "PREMIUM",
                  "kind": "compute#accessConfig"
                }
              ]
            }

        Returns: None

        """
        if 'accessConfigs' in network_interface and 'natIP' in \
                network_interface['accessConfigs'][0]:
            self.external_ip = network_interface['accessConfigs'][0]['natIP']
        else:
            self.external_ip = None
        return self.external_ip

    def preserve_ip_addresses_handler(self, preserve_external_ip):
        """Preserve the IP address.

        Args:
            preserve_external_ip: boolean. Preserving the external ip or not

        """

        if preserve_external_ip and self.external_ip != None:
            print('Preserving the external IP address')
            # There is no external ip assigned to the original VM
            # An ephemeral external ip will be assigned to the new VM

            external_ip_address_body = self.generate_external_ip_address_body()
            try:
                preserve_external_ip_operation = self.preserve_external_ip_address(
                    external_ip_address_body)
                self.operations.wait_for_region_operation(
                    preserve_external_ip_operation['name'])
            except Exception as e:
                if isinstance(e, HttpError) and \
                        'already reserved' in e._get_reason():
                    # The external IP is already preserved as a static IP,
                    return
                warnings.warn(
                    'Failed to preserve the external IP address as a static IP.',
                    Warning)
                raise e
            else:
                print('%s is reserved as a static IP address.' %
                      (self.external_ip))
        else:
            self.external_ip = None

    def preserve_external_ip_address(self, address_body):
        """ Preserve the external IP address.

        Args:
            address_body: internal IP address information, such as
               {
                  name: "ADDRESS_NAME",
                  address: "IP_ADDRESS"
                }
        Returns: a deserialized object of the response

        Raises:
            googleapiclient.errors.HttpError: If the IP
            address is already a static one, or if the IP is not being
            used by any instance, or invalid request, it will raise an Http error
        """
        preserve_external_ip_operation = self.compute.addresses().insert(
            project=self.project, region=self.region,
            body=address_body).execute()
        self.operations.wait_for_region_operation(
            preserve_external_ip_operation['name'])
        return preserve_external_ip_operation

    def generate_external_ip_address_body(self) -> dict:
        """Generate body of an external IP address.

        Returns:
              {
              name: "ADDRESS_NAME",
              address: "IP_ADDRESS"
            }
        """
        if self.external_ip == None:
            raise AttributeNotExistError
        external_ip_address_body = {}
        external_ip_address_body[
            'name'] = self.project + '-' + self.region + '-' + generate_timestamp_string(
            )
        external_ip_address_body['address'] = self.external_ip
        return external_ip_address_body
Ejemplo n.º 17
0
class RegionalBackendService(BackendService):
    def __init__(self, compute, project, backend_service_name, network,
                 subnetwork, preserve_instance_external_ip, region):
        """ Initialization

        Args:
            compute: google compute engine
            project: project ID
            backend_service_name: name of the backend service
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the external IP
            region: region of the load balancer
        """
        super(RegionalBackendService, self).__init__(compute, project,
                                                     backend_service_name,
                                                     network, subnetwork,
                                                     preserve_instance_external_ip)
        self.region = region
        self.backend_service_configs = self.get_backend_service_configs()
        self.operations = Operations(self.compute, self.project, None,
                                     self.region)
        self.network_object = self.build_network_object()
        self.new_backend_service_configs = self.get_new_backend_config_with_new_network_info(
            self.backend_service_configs)
        self.log()

    def get_backend_service_configs(self):
        """ Get the configs of the backend service

        Returns: a deserialized python object of the response

        """
        return self.compute.regionBackendServices().get(
            project=self.project,
            region=self.region,
            backendService=self.backend_service_name).execute()

    def build_network_object(self):
        """ Build network object

        Returns: SubnetNetwork object

        """
        subnetwork_factory = SubnetNetworkHelper(self.compute, self.project,
                                                 None, self.region)
        network_object = subnetwork_factory.generate_network(
            self.network,
            self.subnetwork)
        return network_object

    def get_new_forwarding_rule_with_new_network_info(self,
                                                      forwarding_rule_configs):
        """ Generate a new forwarding rule with the new network info

        Args:
            forwarding_rule_configs:

        Returns:

        """
        new_forwarding_rule_configs = deepcopy(forwarding_rule_configs)
        new_forwarding_rule_configs[
            'network'] = self.network_object.network_link
        new_forwarding_rule_configs[
            'subnetwork'] = self.network_object.subnetwork_link
        return new_forwarding_rule_configs

    def get_new_backend_config_with_new_network_info(self,
                                                     backend_service_configs):
        """ Generate a new backend configs with the new network info

        Args:
            backend_service_configs: configs of the backend service

        Returns:

        """
        new_backend_configs = deepcopy(backend_service_configs)
        new_backend_configs['network'] = self.network_object.network_link
        return new_backend_configs

    def delete_backend_service(self):
        """ Delete the backend service

             Returns: a deserialized python object of the response

        """
        delete_backend_service_operation = self.compute.regionBackendServices(
        ).delete(
            project=self.project,
            region=self.region,
            backendService=self.backend_service_name).execute()
        self.operations.wait_for_region_operation(
            delete_backend_service_operation['name'])
        return delete_backend_service_operation

    def insert_backend_service(self, backend_service_configs):
        """ Insert the backend service

             Returns: a deserialized python object of the response

        """
        insert_backend_service_operation = self.compute.regionBackendServices(
        ).insert(
            project=self.project,
            region=self.region,
            body=backend_service_configs).execute()
        self.operations.wait_for_region_operation(
            insert_backend_service_operation['name'])
        return insert_backend_service_operation

    def check_backend_service_exists(self) -> bool:
        """ Check if the backend service exists in the compute engine

        Returns: True or False

        """
        try:
            self.get_backend_service_configs()
        except HttpError:
            return False
        else:
            return True

    def get_connecting_forwarding_rule_list(self):
        """ Get the configs of the forwarding rule which serves this backend service

        Returns: a deserialized python object of the response

        """
        forwarding_rule_list = []
        backend_service_selfLink = self.backend_service_configs['selfLink']

        request = self.compute.forwardingRules().list(project=self.project,
                                                      region=self.region)
        while request is not None:
            response = request.execute()
            if 'items' not in response:
                break
            for forwarding_rule in response['items']:
                if 'backendService' in forwarding_rule and forwarding_rule[
                    'backendService'] == backend_service_selfLink:
                    forwarding_rule_list.append(forwarding_rule)

            request = self.compute.forwardingRules().list_next(
                previous_request=request,
                previous_response=response)
        return forwarding_rule_list

    def check_backend_health(self, backend_selfLink) -> bool:
        """ Check if the backends is healthy

        Args:
            backends_selfLink: url selfLink of the backends (just an instance group)

        Returns:

        """
        operation = self.compute.regionBackendServices().getHealth(
            project=self.project,
            region=self.region,
            backendService=self.backend_service_name,
            body={
                "group": backend_selfLink
            }).execute()
        if 'healthStatus' not in operation or operation[
            'healthStatus'] != 'HEALTHY':
            return False

        return True
class RegionalForwardingRule(ForwardingRule):
    def __init__(self, compute, project, forwarding_rule_name, network,
                 subnetwork, region):
        """ Initialization

        Args:
            compute: google compute engine
            project: project id
            forwarding_rule_name: the name of the forwarding rule
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the IPs of
                the instances serving the forwarding rule
            region: region of the forwarding rule
        """
        super(RegionalForwardingRule,
              self).__init__(compute, project, forwarding_rule_name, network,
                             subnetwork)
        self.region = region
        self.forwarding_rule_configs = self.get_forwarding_rule_configs()
        self.operations = Operations(self.compute, self.project, None,
                                     self.region)
        self.log()

    def get_forwarding_rule_configs(self):
        """ Get the configs of the forwarding rule

        Returns: configs

        """
        return self.compute.forwardingRules().get(
            project=self.project,
            region=self.region,
            forwardingRule=self.forwarding_rule_name).execute()

    def check_forwarding_rule_exists(self) -> bool:
        """ Check if the forwarding rule exists

        Returns: True or False

        """
        try:
            self.get_forwarding_rule_configs()
        except:
            return False
        else:
            return True

    def delete_forwarding_rule(self) -> dict:
        """ Delete the forwarding rule

             Returns: a deserialized python object of the response

        """
        delete_forwarding_rule_operation = self.compute.forwardingRules(
        ).delete(project=self.project,
                 region=self.region,
                 forwardingRule=self.forwarding_rule_name).execute()
        self.operations.wait_for_region_operation(
            delete_forwarding_rule_operation['name'])
        return delete_forwarding_rule_operation

    def insert_forwarding_rule(self, forwarding_rule_config):
        """ create the forwarding rule

             Returns: a deserialized python object of the response

        """
        try:
            insert_forwarding_rule_operation = self.compute.forwardingRules(
            ).insert(project=self.project,
                     region=self.region,
                     body=forwarding_rule_config).execute()
            self.operations.wait_for_region_operation(
                insert_forwarding_rule_operation['name'])

        except HttpError as e:
            error_reason = e._get_reason()
            if 'internal IP is outside' in error_reason:
                warnings.warn('The original IP address of the forwarding rule was an ' \
                    'ephemeral one. After the migration, a new IP address is ' \
                    'assigned to the forwarding rule.', Warning)
            else:
                warnings.warn(error_reason, Warning)
                # Set the IPAddress to ephemeral
            if 'IPAddress' in forwarding_rule_config:
                del forwarding_rule_config['IPAddress']
            insert_forwarding_rule_operation = self.compute.forwardingRules(
            ).insert(project=self.project,
                     region=self.region,
                     body=forwarding_rule_config).execute()
            self.operations.wait_for_region_operation(
                insert_forwarding_rule_operation['name'])

        return insert_forwarding_rule_operation
class TargetPool:
    @initializer
    def __init__(self, compute, project, target_pool_name, region, network,
                 subnetwork, preserve_instance_external_ip):
        """ Initialization

        Args:
            compute: google compute engine
            project: project id
            target_pool_name: name of the target pool
            region: name of the region
            network: target network
            subnetwork: target subnet
            preserve_instance_external_ip: whether to preserve the external IPs
            of the instances serving the backends
        """

        self.target_pool_config = self.get_target_pool_configs()
        self.log()
        self.selfLink = self.get_selfLink()
        self.operations = Operations(self.compute, self.project, None,
                                     self.region)
        # The instances which don't belong to any instance groups
        self.attached_single_instances_selfLinks = []
        self.attached_managed_instance_groups_selfLinks = []
        self.get_attached_backends()

    def log(self):
        logging.basicConfig(filename='backup.log', level=logging.INFO)
        logging.info('-------Target Pool: %s-----' % (self.target_pool_name))
        logging.info(self.target_pool_config)
        logging.info('--------------------------')

    def get_target_pool_configs(self):
        """ Get the configs of the target pool

        Returns: a deserialized python object of the response

        """
        return self.compute.targetPools().get(
            project=self.project,
            region=self.region,
            targetPool=self.target_pool_name).execute()

    def get_selfLink(self):
        """ Get the selfLink of the target pool

        Returns: URL string

        """
        if 'selfLink' in self.target_pool_config:
            return self.target_pool_config['selfLink']

    def add_instance(self, instance_selfLink):
        """ Add an instance into the backends

        Returns: a deserialized python object of the response

        """
        add_instance_operation = self.compute.targetPools().addInstance(
            project=self.project,
            region=self.region,
            targetPool=self.target_pool_name,
            body={
                'instances': [{
                    'instance': instance_selfLink
                }]
            }).execute()
        self.operations.wait_for_region_operation(
            add_instance_operation['name'])
        return add_instance_operation

    def remove_instance(self, instance_selfLink):
        """ Remove an instance from the backends

              Returns: a deserialized python object of the response

        """
        remove_instance_operation = self.compute.targetPools().removeInstance(
            project=self.project,
            region=self.region,
            targetPool=self.target_pool_name,
            body={
                'instances': [{
                    'instance': instance_selfLink
                }]
            }).execute()
        self.operations.wait_for_region_operation(
            remove_instance_operation['name'])
        return remove_instance_operation

    def get_attached_backends(self):
        """ According to the target pool configs, the attached instances
        can be found. These instances can be a single instance which does
        not belong to any instance group, but they can also belongs to an
        unmanaged instance group or a managed instance group. This function
        can get all these information and store the Instance objects and
        Instance group objects into the attributes.

        """
        instance_group_and_instances = {}
        for instance_selfLink in self.target_pool_config['instances']:
            instance_selfLink_executor = SelfLinkExecutor(
                self.compute, instance_selfLink, self.network, self.subnetwork,
                self.preserve_instance_external_ip)
            try:
                instance = instance_selfLink_executor.build_an_instance()
                instance_group_selfLinks = instance.get_referrer_selfLinks()
            except HttpError as e:
                error_message = e._get_reason()
                if 'not found' in error_message:
                    continue
                else:
                    raise e
            # No instance group is associated with this instance
            if len(instance_group_selfLinks) == 0:
                self.attached_single_instances_selfLinks.append(
                    instance.selfLink)
            else:
                for selfLink in instance_group_selfLinks:
                    if selfLink in instance_group_and_instances:
                        instance_group_and_instances[selfLink].append(
                            instance.selfLink)
                    else:
                        instance_group_and_instances[selfLink] = [
                            instance.selfLink
                        ]

        for instance_group_selfLink, instance_selfLink_list in instance_group_and_instances.items(
        ):
            instance_group_selfLink_executor = SelfLinkExecutor(
                self.compute, instance_group_selfLink, self.network,
                self.subnetwork, self.preserve_instance_external_ip)

            instance_group = instance_group_selfLink_executor.build_an_instance_group(
            )
            if isinstance(instance_group, UnmanagedInstanceGroup):
                raise AmbiguousTargetResource(
                    'The instance %s is within an unmanaged instance group %s. '
                    'If you want to migrate this instance group, you should '
                    'detach this instance or this instance group from the '
                    'target pool, and then call the instance group migration '
                    'method instead. After detaching, you can try to migrate '
                    'the instaces of this target pool again.' %
                    (instance_selfLink_list, instance_group_selfLink))

            else:
                target_pool_list = instance_group.get_target_pools()
                if len(target_pool_list) == 1 and self.selfLink == \
                        target_pool_list[0]:
                    self.attached_managed_instance_groups_selfLinks.append(
                        instance_group.selfLink)
                elif self.selfLink not in target_pool_list:
                    raise AmbiguousTargetResource(
                        'The instances %s are within a managed instance group %s, \n'
                        'but this instance group is not serving the target pool. \n'
                        'If you want to migrate this instance group, please \n'
                        'detach these instances from the target pool and then \n'
                        'try out the instance group migration method. \n'
                        'After detaching the instances, you can also try to \n'
                        'migrate the instances of the target pool again. ' %
                        (instance_selfLink_list, instance_group_selfLink))
                else:
                    raise MultipleTargetPools(
                        "The instance group %s is serving multiple target pools, \n"
                        " please detach it from the other target pools or \n"
                        "backend services and try again." %
                        (instance_group_selfLink))

    def check_backend_health(self, backend_selfLink):
        """ Check if the backend is healthy

        Args:
            backends_selfLink: url selfLink of the backend (just an instance)

        Returns:

        """
        operation = self.compute.targetPools().getHealth(
            project=self.project,
            targetPool=self.target_pool_name,
            region=self.region,
            body={
                "instance": backend_selfLink
            }).execute()
        if 'healthStatus' not in operation:
            return False
        else:
            for instance_health_status in operation['healthStatus']:
                # If any instance in this backend becomes healthy,
                # this backend will start serving the backend service
                if 'healthState' in instance_health_status and \
                        instance_health_status['healthState'] == 'HEALTHY':
                    return True
        return False

    def wait_for_instance_become_healthy(self,
                                         instance_selfLink,
                                         TIME_OUT=300):
        """ Wait for an instance being healthy

        Args:
            backend_selfLink: url selfLink of the backends (just an instance group)

        Returns:

        """
        start = datetime.now()
        print('Waiting for %s being healthy with time out %s seconds.' %
              (instance_selfLink, TIME_OUT))
        while not self.check_backend_health(instance_selfLink):
            time.sleep(3)
            current_time = datetime.now()
            if (current_time - start).seconds > TIME_OUT:
                print('Health waiting operation is timed out.')
                return
        print('At least one of the backend in %s is healthy.' %
              (self.target_pool_name))

    def wait_for_an_instance_group_become_partially_healthy(
            self, instance_group, TIME_OUT=300):
        """ Wait for at least one instance in this instance group being healthy

        Args:
            instance_group:  a ManagedInstanceGroup object
            TIME_OUT: maximum waiting time

        Returns:

        """
        start = datetime.now()
        print('Waiting for %s being healthy with timeout %s seconds.' %
              (instance_group.selfLink, TIME_OUT))
        while (datetime.now() - start).seconds < TIME_OUT:
            instance_selfLinks = instance_group.list_instances()
            for instance_selfLink in instance_selfLinks:
                try:
                    if self.check_backend_health(instance_selfLink):
                        print('At least one of the backend in %s is healthy.' %
                              (self.target_pool_name))
                        return
                except:
                    # the instance maybe hasn't been attached to the target pool
                    continue
            time.sleep(5)
Ejemplo n.º 20
0
class Instance(object):
    @initializer
    def __init__(self,
                 compute,
                 project,
                 name,
                 zone,
                 network,
                 subnetwork,
                 preserve_instance_ip=False,
                 instance_configs=None):
        """ Initialize an instance object

        Args:
            compute: google compute engine
            project: project ID
            name: name of the instance
            region: region of the instance
            zone: zone of the instance
            instance_configs: the instance config
        """

        self.original_instance_configs = instance_configs or self.retrieve_instance_configs(
        )
        self.network_object = self.get_network()
        self.address_object = self.get_address()
        self.new_instance_configs = self.get_new_instance_configs()
        self.original_status = self.get_instance_status()
        self.operations = Operations(compute, project, zone)
        self.selfLink = self.get_selfLink(self.original_instance_configs)
        self.log()

    def log(self):
        logging.basicConfig(filename='backup.log', level=logging.INFO)
        logging.info('-------Instance: %s-----' % (self.name))
        logging.info(self.original_instance_configs)
        logging.info('--------------------------')

    def retrieve_instance_configs(self) -> dict:
        """ Get the instance config.

        Returns:
            config of the instance

        Raises:
            googleapiclient.errors.HttpError: invalid request
        """
        instance_configs = self.compute.instances().get(
            project=self.project, zone=self.zone,
            instance=self.name).execute()

        return instance_configs

    def get_address(self):
        """ Generate the address object

        Returns: Address object

        """
        if self.original_instance_configs == None:
            self.original_instance_configs = self.retrieve_instance_configs()
        address_factory = AddressHelper(self.compute, self.project, self.zone)
        address = address_factory.generate_address(
            self.original_instance_configs)
        return address

    def get_network(self):
        """ Generate the network object

        Returns: Network object

        """
        subnetwork_factory = SubnetNetworkHelper(self.compute, self.project,
                                                 self.zone)
        network = subnetwork_factory.generate_network(self.network,
                                                      self.subnetwork)
        return network

    def get_selfLink(self, instance_configs) -> str:
        """ Get the instance selfLink from its configs

        Args:
            instance_configs: instance configurations

        Returns: string of a URL link

        """
        if 'selfLink' in instance_configs:
            return instance_configs['selfLink']

    def start_instance(self) -> dict:
        """ Start the instance.

        Returns:
            a deserialized object of the response

        Raises:
            googleapiclient.errors.HttpError: invalid request
        """
        start_instance_operation = self.compute.instances().start(
            project=self.project, zone=self.zone,
            instance=self.name).execute()
        self.operations.wait_for_zone_operation(
            start_instance_operation['name'])
        return start_instance_operation

    def stop_instance(self) -> dict:
        """ Stop the instance.

        Returns:
            a deserialized object of the response

        Raises:
            googleapiclient.errors.HttpError: invalid request
        """
        stop_instance_operation = self.compute.instances().stop(
            project=self.project, zone=self.zone,
            instance=self.name).execute()
        self.operations.wait_for_zone_operation(
            stop_instance_operation['name'])
        return stop_instance_operation

    def get_disks_info_from_instance_configs(self) -> list:
        """ Get disks' info from the instance config.

        Returns:
            a list of disks' info

        Raises:
            AttributeNotExistError: No disks on the VM
        """
        if 'disks' not in self.original_instance_configs:
            raise AttributeNotExistError('No disks are attached on the VM')
        return self.original_instance_configs['disks']

    def detach_disk(self, disk) -> dict:
        """ Detach a disk from the instance

        Args:
            disk: name of the disk

        Returns:
            a deserialized object of the response

        Raises:
            googleapiclient.errors.HttpError: invalid request
        """

        detach_disk_operation = self.compute.instances().detachDisk(
            project=self.project,
            zone=self.zone,
            instance=self.name,
            deviceName=disk).execute()
        self.operations.wait_for_zone_operation(detach_disk_operation['name'])
        return detach_disk_operation

    def detach_disks(self):
        """ Detach all the disks retrieved from self.instance_configs

        Returns: None

        """
        disks = self.get_disks_info_from_instance_configs()
        for diskInfo in disks:
            self.detach_disk(diskInfo['deviceName'])

    def attach_disk(self, diskInfo):
        """Attach a disk to the instance

        Args:
            disk: deserialized info of the disk

        Returns:
            a deserialized object of the response

        Raises:
            googleapiclient.errors.HttpError: invalid request
        """
        attach_disk_operation = self.compute.instances().attachDisk(
            project=self.project,
            zone=self.zone,
            instance=self.name,
            forceAttach=True,
            body=diskInfo).execute()
        self.operations.wait_for_zone_operation(attach_disk_operation['name'])
        return attach_disk_operation

    def attach_disks(self):
        """ Attach all the disks retrieved from self.instance_configs

        Returns: None
        """
        disks = self.get_disks_info_from_instance_configs()
        for diskInfo in disks:
            self.attach_disk(diskInfo)

    def modify_instance_configs_with_new_network(self,
                                                 new_network_link,
                                                 new_subnetwork_link,
                                                 instance_configs,
                                                 add_network_metadata=True):
        """ Modify the instance config with the new network links

            Args:
                new_network_link: the selflink of the network
                new_subnetwork_link: the selflink of the subnetwork

            Returns:
                modified instance config
        """
        instance_configs['networkInterfaces'][0]['network'] = new_network_link
        instance_configs['networkInterfaces'][0][
            'subnetwork'] = new_subnetwork_link
        # For testing
        # if add_network_metadata:
        #     if 'items' not in instance_configs['metadata']:
        #         instance_configs['metadata']['items'] = []
        #
        #     for item in instance_configs['metadata']['items']:
        #         if item['key'] == 'network':
        #             item['value'] = new_subnetwork_link
        #             return
        #
        #     instance_configs['metadata']['items'].append({
        #         'key': 'network',
        #         'value': new_subnetwork_link})

    def modify_instance_configs_with_external_ip(self, external_ip,
                                                 instance_configs):
        """ Modify the instance config with the given external IP address

        Args:
            external_ip: external IP address, such as "123.213.213.123"

        Returns: modified instance config

        """
        if external_ip == None:
            if 'accessConfigs' in instance_configs['networkInterfaces'][0]:
                if 'natIP' in instance_configs['networkInterfaces'][0][
                        'accessConfigs'][0]:
                    del \
                        instance_configs['networkInterfaces'][0][
                            'accessConfigs'][
                            0]['natIP']

        else:
            if 'accessConfigs' not in \
                    instance_configs['networkInterfaces'][0]:
                instance_configs['networkInterfaces'][0]['accessConfigs'] = [
                    {}
                ]
            instance_configs['networkInterfaces'][0]['accessConfigs'][0][
                'natIP'] = external_ip

        if 'networkIP' in instance_configs['networkInterfaces'][0]:
            del instance_configs['networkInterfaces'][0]['networkIP']

    def get_new_instance_configs(self):
        """ Update the instance config with current attributes

        Returns: None

        """
        new_instance_configs = deepcopy(self.original_instance_configs)
        if self.address_object == None or self.network == None:
            raise AttributeNotExistError('Missing address or network object.')
        if not self.preserve_instance_ip:
            self.modify_instance_configs_with_external_ip(
                None, new_instance_configs)
        else:
            self.modify_instance_configs_with_external_ip(
                self.address_object.external_ip, new_instance_configs)
        self.modify_instance_configs_with_new_network(
            self.network_object.network_link,
            self.network_object.subnetwork_link, new_instance_configs)
        return new_instance_configs

    def create_instance(self, instance_configs) -> dict:
        """ Create the instance using self.instance_configs

            Returns:
                a deserialized object of the response

            Raises:
                googleapiclient.errors.HttpError: invalid request
        """
        create_instance_operation = self.compute.instances().insert(
            project=self.project, zone=self.zone,
            body=instance_configs).execute()
        self.operations.wait_for_zone_operation(
            create_instance_operation['name'])
        return create_instance_operation

    def delete_instance(self) -> dict:
        """ Delete the instance

            Returns:
                a deserialized object of the response

            Raises:
                googleapiclient.errors.HttpError: invalid request
        """
        delete_instance_operation = self.compute.instances().delete(
            project=self.project, zone=self.zone,
            instance=self.name).execute()
        self.operations.wait_for_zone_operation(
            delete_instance_operation['name'])
        return delete_instance_operation

    def get_instance_status(self):
        """ Get current instance's status.

        Returns: an InstanceStatus object
        Raises: HttpError for incorrect response
        """
        try:
            instance_configs = self.retrieve_instance_configs()
        except HttpError as e:
            error_reason = e._get_reason()
            print(error_reason)
            # if instance is not found, it has a NOTEXISTS status
            if 'not found' in error_reason:
                return InstanceStatus.NOTEXISTS
            else:
                raise e
        return InstanceStatus(instance_configs['status'])

    def create_instance_with_ephemeral_external_ip(self, configs) -> dict:
        """ Create instance using configs, but without static external IP.

        Args:
            configs: configs of the instance

        """
        cur_configs = deepcopy(configs)
        self.modify_instance_configs_with_external_ip(None, cur_configs)
        print('Modified VM configuration:', cur_configs)
        return self.create_instance(cur_configs)

    def get_referrer_selfLinks(self) -> list:
        """ Get all this instance's referrer's selfLinks

        Returns:a list of instance group selfLinks

        """
        referrer_selfLinks = []
        request = self.compute.instances().listReferrers(project=self.project,
                                                         zone=self.zone,
                                                         instance=self.name)
        while request is not None:
            response = request.execute()
            if 'items' not in response:
                break

            for reference in response['items']:
                if 'MEMBER_OF' in reference['referenceType']:
                    referrer_selfLinks.append(reference['referrer'])

            request = self.compute.instances().listReferrers_next(
                previous_request=request, previous_response=response)
        return referrer_selfLinks

    def compare_original_network_and_target_network(self):
        """ Check if the original network is the
        same as the target subnet

        Returns: True for the same
        """
        if self.network_object == None or self.network_object.subnetwork_link == None:
            raise InvalidTargetNetworkError

        if 'subnetwork' not in \
                self.original_instance_configs['networkInterfaces'][0]:
            return False
        elif is_equal_or_contians(
                self.original_instance_configs['networkInterfaces'][0]
            ['subnetwork'], self.network_object.subnetwork_link):
            return True
        else:
            return False