You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2014/07/21 15:53:11 UTC
[1/2] Remove duplicated file.
Repository: libcloud
Updated Branches:
refs/heads/trunk feea74d3f -> 075383509
http://git-wip-us.apache.org/repos/asf/libcloud/blob/07538350/libcloud/compute/drivers/gce.py.orig
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/gce.py.orig b/libcloud/compute/drivers/gce.py.orig
deleted file mode 100644
index c216c64..0000000
--- a/libcloud/compute/drivers/gce.py.orig
+++ /dev/null
@@ -1,3353 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-Module for Google Compute Engine Driver.
-"""
-from __future__ import with_statement
-
-import datetime
-import time
-import sys
-
-from libcloud.common.google import GoogleResponse
-from libcloud.common.google import GoogleBaseConnection
-from libcloud.common.google import GoogleBaseError
-from libcloud.common.google import ResourceNotFoundError
-from libcloud.common.google import ResourceExistsError
-
-from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation
-from libcloud.compute.base import NodeSize, StorageVolume, VolumeSnapshot
-from libcloud.compute.base import UuidMixin
-from libcloud.compute.providers import Provider
-from libcloud.compute.types import NodeState
-
-API_VERSION = 'v1'
-DEFAULT_TASK_COMPLETION_TIMEOUT = 180
-
-
-def timestamp_to_datetime(timestamp):
- """
- Return a datetime object that corresponds to the time in an RFC3339
- timestamp.
-
- :param timestamp: RFC3339 timestamp string
- :type timestamp: ``str``
-
- :return: Datetime object corresponding to timestamp
- :rtype: :class:`datetime.datetime`
- """
- # We remove timezone offset and microseconds (Python 2.5 strptime doesn't
- # support %f)
- ts = datetime.datetime.strptime(timestamp[:-10], '%Y-%m-%dT%H:%M:%S')
- tz_hours = int(timestamp[-5:-3])
- tz_mins = int(timestamp[-2:]) * int(timestamp[-6:-5] + '1')
- tz_delta = datetime.timedelta(hours=tz_hours, minutes=tz_mins)
- return ts + tz_delta
-
-
-class GCEResponse(GoogleResponse):
- pass
-
-
-class GCEConnection(GoogleBaseConnection):
- """Connection class for the GCE driver."""
- host = 'www.googleapis.com'
- responseCls = GCEResponse
-
- def __init__(self, user_id, key, secure, auth_type=None,
- credential_file=None, project=None, **kwargs):
- super(GCEConnection, self).__init__(user_id, key, secure=secure,
- auth_type=auth_type,
- credential_file=credential_file,
- **kwargs)
- self.request_path = '/compute/%s/projects/%s' % (API_VERSION,
- project)
-
-
-class GCEAddress(UuidMixin):
- """A GCE Static address."""
- def __init__(self, id, name, address, region, driver, extra=None):
- self.id = str(id)
- self.name = name
- self.address = address
- self.region = region
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def destroy(self):
- """
- Destroy this address.
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_destroy_address(address=self)
-
- def __repr__(self):
- return '<GCEAddress id="%s" name="%s" address="%s">' % (
- self.id, self.name, self.address)
-
-
-class GCEFailedDisk(object):
- """Dummy Node object for disks that are not created."""
- def __init__(self, name, error, code):
- self.name = name
- self.error = error
- self.code = code
-
- def __repr__(self):
- return '<GCEFailedDisk name="%s" error_code="%s">' % (
- self.name, self.code)
-
-
-class GCEFailedNode(object):
- """Dummy Node object for nodes that are not created."""
- def __init__(self, name, error, code):
- self.name = name
- self.error = error
- self.code = code
-
- def __repr__(self):
- return '<GCEFailedNode name="%s" error_code="%s">' % (
- self.name, self.code)
-
-
-class GCEHealthCheck(UuidMixin):
- """A GCE Http Health Check class."""
- def __init__(self, id, name, path, port, interval, timeout,
- unhealthy_threshold, healthy_threshold, driver, extra=None):
- self.id = str(id)
- self.name = name
- self.path = path
- self.port = port
- self.interval = interval
- self.timeout = timeout
- self.unhealthy_threshold = unhealthy_threshold
- self.healthy_threshold = healthy_threshold
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def destroy(self):
- """
- Destroy this Health Check.
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_destroy_healthcheck(healthcheck=self)
-
- def update(self):
- """
- Commit updated healthcheck values.
-
- :return: Updated Healthcheck object
- :rtype: :class:`GCEHealthcheck`
- """
- return self.driver.ex_update_healthcheck(healthcheck=self)
-
- def __repr__(self):
- return '<GCEHealthCheck id="%s" name="%s" path="%s" port="%s">' % (
- self.id, self.name, self.path, self.port)
-
-
-class GCEFirewall(UuidMixin):
- """A GCE Firewall rule class."""
- def __init__(self, id, name, allowed, network, source_ranges, source_tags,
- target_tags, driver, extra=None):
- self.id = str(id)
- self.name = name
- self.network = network
- self.allowed = allowed
- self.source_ranges = source_ranges
- self.source_tags = source_tags
- self.target_tags = target_tags
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def destroy(self):
- """
- Destroy this firewall.
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_destroy_firewall(firewall=self)
-
- def update(self):
- """
- Commit updated firewall values.
-
- :return: Updated Firewall object
- :rtype: :class:`GCEFirewall`
- """
- return self.driver.ex_update_firewall(firewall=self)
-
- def __repr__(self):
- return '<GCEFirewall id="%s" name="%s" network="%s">' % (
- self.id, self.name, self.network.name)
-
-
-class GCEForwardingRule(UuidMixin):
- def __init__(self, id, name, region, address, protocol, targetpool, driver,
- extra=None):
- self.id = str(id)
- self.name = name
- self.region = region
- self.address = address
- self.protocol = protocol
- self.targetpool = targetpool
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def destroy(self):
- """
- Destroy this Forwarding Rule
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_destroy_forwarding_rule(forwarding_rule=self)
-
- def __repr__(self):
- return '<GCEForwardingRule id="%s" name="%s" address="%s">' % (
- self.id, self.name, self.address)
-
-
-class GCENodeImage(NodeImage):
- """A GCE Node Image class."""
- def __init__(self, id, name, driver, extra=None):
- super(GCENodeImage, self).__init__(id, name, driver, extra=extra)
-
- def delete(self):
- """
- Delete this image
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_delete_image(image=self)
-
- def deprecate(self, replacement, state):
- """
- Deprecate this image
-
- :param replacement: Image to use as a replacement
- :type replacement: ``str`` or :class: `GCENodeImage`
-
- :param state: Deprecation state of this image. Possible values include
- \'DELETED\', \'DEPRECATED\' or \'OBSOLETE\'.
- :type state: ``str``
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_deprecate_image(self, replacement, state)
-
-
-class GCENetwork(UuidMixin):
- """A GCE Network object class."""
- def __init__(self, id, name, cidr, driver, extra=None):
- self.id = str(id)
- self.name = name
- self.cidr = cidr
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def destroy(self):
- """
- Destroy this network
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_destroy_network(network=self)
-
- def __repr__(self):
- return '<GCENetwork id="%s" name="%s" cidr="%s">' % (
- self.id, self.name, self.cidr)
-
-
-class GCENodeSize(NodeSize):
- """A GCE Node Size (MachineType) class."""
- def __init__(self, id, name, ram, disk, bandwidth, price, driver,
- extra=None):
- self.extra = extra
- super(GCENodeSize, self).__init__(id, name, ram, disk, bandwidth,
- price, driver, extra=extra)
-
-
-class GCEProject(UuidMixin):
- """GCE Project information."""
- def __init__(self, id, name, metadata, quotas, driver, extra=None):
- self.id = str(id)
- self.name = name
- self.metadata = metadata
- self.quotas = quotas
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def __repr__(self):
- return '<GCEProject id="%s" name="%s">' % (self.id, self.name)
-
-
-class GCERegion(UuidMixin):
- def __init__(self, id, name, status, zones, quotas, deprecated, driver,
- extra=None):
- self.id = str(id)
- self.name = name
- self.status = status
- self.zones = zones
- self.quotas = quotas
- self.deprecated = deprecated
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def __repr__(self):
- return '<GCERegion id="%s" name="%s", status="%s">' % (
- self.id, self.name, self.status)
-
-
-class GCESnapshot(VolumeSnapshot):
- def __init__(self, id, name, size, status, driver, extra=None):
- self.name = name
- self.status = status
- super(GCESnapshot, self).__init__(id, driver, size, extra)
-
-
-class GCETargetPool(UuidMixin):
- def __init__(self, id, name, region, healthchecks, nodes, driver,
- extra=None):
- self.id = str(id)
- self.name = name
- self.region = region
- self.healthchecks = healthchecks
- self.nodes = nodes
- self.driver = driver
- self.extra = extra
- UuidMixin.__init__(self)
-
- def add_node(self, node):
- """
- Add a node to this target pool.
-
- :param node: Node to add
- :type node: ``str`` or :class:`Node`
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_targetpool_add_node(targetpool=self, node=node)
-
- def remove_node(self, node):
- """
- Remove a node from this target pool.
-
- :param node: Node to remove
- :type node: ``str`` or :class:`Node`
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_targetpool_remove_node(targetpool=self,
- node=node)
-
- def add_healthcheck(self, healthcheck):
- """
- Add a healthcheck to this target pool.
-
- :param healthcheck: Healthcheck to add
- :type healthcheck: ``str`` or :class:`GCEHealthCheck`
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_targetpool_add_healthcheck(
- targetpool=self, healthcheck=healthcheck)
-
- def remove_healthcheck(self, healthcheck):
- """
- Remove a healthcheck from this target pool.
-
- :param healthcheck: Healthcheck to remove
- :type healthcheck: ``str`` or :class:`GCEHealthCheck`
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_targetpool_remove_healthcheck(
- targetpool=self, healthcheck=healthcheck)
-
- def destroy(self):
- """
- Destroy this Target Pool
-
- :return: True if successful
- :rtype: ``bool``
- """
- return self.driver.ex_destroy_targetpool(targetpool=self)
-
- def __repr__(self):
- return '<GCETargetPool id="%s" name="%s" region="%s">' % (
- self.id, self.name, self.region.name)
-
-
-class GCEZone(NodeLocation):
- """Subclass of NodeLocation to provide additional information."""
- def __init__(self, id, name, status, maintenance_windows, deprecated,
- driver, extra=None):
- self.status = status
- self.maintenance_windows = maintenance_windows
- self.deprecated = deprecated
- self.extra = extra
- country = name.split('-')[0]
- super(GCEZone, self).__init__(id=str(id), name=name, country=country,
- driver=driver)
-
- @property
- def time_until_mw(self):
- """
- Returns the time until the next Maintenance Window as a
- datetime.timedelta object.
- """
- return self._get_time_until_mw()
-
- @property
- def next_mw_duration(self):
- """
- Returns the duration of the next Maintenance Window as a
- datetime.timedelta object.
- """
- return self._get_next_mw_duration()
-
- def _now(self):
- """
- Returns current UTC time.
-
- Can be overridden in unittests.
- """
- return datetime.datetime.utcnow()
-
- def _get_next_maint(self):
- """
- Returns the next Maintenance Window.
-
- :return: A dictionary containing maintenance window info (or None if
- no maintenance windows are scheduled)
- The dictionary contains 4 keys with values of type ``str``
- - name: The name of the maintenance window
- - description: Description of the maintenance window
- - beginTime: RFC3339 Timestamp
- - endTime: RFC3339 Timestamp
- :rtype: ``dict`` or ``None``
- """
- begin = None
- next_window = None
- if not self.maintenance_windows:
- return None
- if len(self.maintenance_windows) == 1:
- return self.maintenance_windows[0]
- for mw in self.maintenance_windows:
- begin_next = timestamp_to_datetime(mw['beginTime'])
- if (not begin) or (begin_next < begin):
- begin = begin_next
- next_window = mw
- return next_window
-
- def _get_time_until_mw(self):
- """
- Returns time until next maintenance window.
-
- :return: Time until next maintenance window (or None if no
- maintenance windows are scheduled)
- :rtype: :class:`datetime.timedelta` or ``None``
- """
- next_window = self._get_next_maint()
- if not next_window:
- return None
- now = self._now()
- next_begin = timestamp_to_datetime(next_window['beginTime'])
- return next_begin - now
-
- def _get_next_mw_duration(self):
- """
- Returns the duration of the next maintenance window.
-
- :return: Duration of next maintenance window (or None if no
- maintenance windows are scheduled)
- :rtype: :class:`datetime.timedelta` or ``None``
- """
- next_window = self._get_next_maint()
- if not next_window:
- return None
- next_begin = timestamp_to_datetime(next_window['beginTime'])
- next_end = timestamp_to_datetime(next_window['endTime'])
- return next_end - next_begin
-
- def __repr__(self):
- return '<GCEZone id="%s" name="%s" status="%s">' % (self.id, self.name,
- self.status)
-
-
-class GCENodeDriver(NodeDriver):
- """
- GCE Node Driver class.
-
- This is the primary driver for interacting with Google Compute Engine. It
- contains all of the standard libcloud methods, plus additional ex_* methods
- for more features.
-
- Note that many methods allow either objects or strings (or lists of
- objects/strings). In most cases, passing strings instead of objects will
- result in additional GCE API calls.
- """
- connectionCls = GCEConnection
- api_name = 'googleapis'
- name = "Google Compute Engine"
- type = Provider.GCE
- website = 'https://cloud.google.com/'
-
- NODE_STATE_MAP = {
- "PROVISIONING": NodeState.PENDING,
- "STAGING": NodeState.PENDING,
- "RUNNING": NodeState.RUNNING,
- "STOPPED": NodeState.TERMINATED,
- "STOPPING": NodeState.TERMINATED,
- "TERMINATED": NodeState.TERMINATED
- }
-
- def __init__(self, user_id, key, datacenter=None, project=None,
- auth_type=None, scopes=None, **kwargs):
- """
- :param user_id: The email address (for service accounts) or Client ID
- (for installed apps) to be used for authentication.
- :type user_id: ``str``
-
- :param key: The RSA Key (for service accounts) or file path containing
- key or Client Secret (for installed apps) to be used for
- authentication.
- :type key: ``str``
-
- :keyword datacenter: The name of the datacenter (zone) used for
- operations.
- :type datacenter: ``str``
-
- :keyword project: Your GCE project name. (required)
- :type project: ``str``
-
- :keyword auth_type: Accepted values are "SA" or "IA"
- ("Service Account" or "Installed Application").
- If not supplied, auth_type will be guessed based
- on value of user_id.
- :type auth_type: ``str``
-
- :keyword scopes: List of authorization URLs. Default is empty and
- grants read/write to Compute, Storage, DNS.
- :type scopes: ``list``
- """
- self.auth_type = auth_type
- self.project = project
- self.scopes = scopes
- if not self.project:
- raise ValueError('Project name must be specified using '
- '"project" keyword.')
- super(GCENodeDriver, self).__init__(user_id, key, **kwargs)
-
- # Cache Zone and Region information to reduce API calls and
- # increase speed
- self.base_path = '/compute/%s/projects/%s' % (API_VERSION,
- self.project)
- self.zone_list = self.ex_list_zones()
- self.zone_dict = {}
- for zone in self.zone_list:
- self.zone_dict[zone.name] = zone
- if datacenter:
- self.zone = self.ex_get_zone(datacenter)
- else:
- self.zone = None
-
- self.region_list = self.ex_list_regions()
- self.region_dict = {}
- for region in self.region_list:
- self.region_dict[region.name] = region
-
- if self.zone:
- self.region = self._get_region_from_zone(self.zone)
- else:
- self.region = None
-
- def ex_list_addresses(self, region=None):
- """
- Return a list of static addresses for a region or all.
-
- :keyword region: The region to return addresses from. For example:
- 'us-central1'. If None, will return addresses from
- region of self.zone. If 'all', will return all
- addresses.
- :type region: ``str`` or ``None``
-
- :return: A list of static address objects.
- :rtype: ``list`` of :class:`GCEAddress`
- """
- list_addresses = []
- region = self._set_region(region)
- if region is None:
- request = '/aggregated/addresses'
- else:
- request = '/regions/%s/addresses' % (region.name)
- response = self.connection.request(request, method='GET').object
-
- if 'items' in response:
- # The aggregated result returns dictionaries for each region
- if region is None:
- for v in response['items'].values():
- region_addresses = [self._to_address(a) for a in
- v.get('addresses', [])]
- list_addresses.extend(region_addresses)
- else:
- list_addresses = [self._to_address(a) for a in
- response['items']]
- return list_addresses
-
- def ex_list_healthchecks(self):
- """
- Return the list of health checks.
-
- :return: A list of health check objects.
- :rtype: ``list`` of :class:`GCEHealthCheck`
- """
- list_healthchecks = []
- request = '/global/httpHealthChecks'
- response = self.connection.request(request, method='GET').object
- list_healthchecks = [self._to_healthcheck(h) for h in
- response.get('items', [])]
- return list_healthchecks
-
- def ex_list_firewalls(self):
- """
- Return the list of firewalls.
-
- :return: A list of firewall objects.
- :rtype: ``list`` of :class:`GCEFirewall`
- """
- list_firewalls = []
- request = '/global/firewalls'
- response = self.connection.request(request, method='GET').object
- list_firewalls = [self._to_firewall(f) for f in
- response.get('items', [])]
- return list_firewalls
-
- def ex_list_forwarding_rules(self, region=None):
- """
- Return the list of forwarding rules for a region or all.
-
- :keyword region: The region to return forwarding rules from. For
- example: 'us-central1'. If None, will return
- forwarding rules from the region of self.region
- (which is based on self.zone). If 'all', will
- return all forwarding rules.
- :type region: ``str`` or :class:`GCERegion` or ``None``
-
- :return: A list of forwarding rule objects.
- :rtype: ``list`` of :class:`GCEForwardingRule`
- """
- list_forwarding_rules = []
- region = self._set_region(region)
- if region is None:
- request = '/aggregated/forwardingRules'
- else:
- request = '/regions/%s/forwardingRules' % (region.name)
- response = self.connection.request(request, method='GET').object
-
- if 'items' in response:
- # The aggregated result returns dictionaries for each region
- if region is None:
- for v in response['items'].values():
- region_forwarding_rules = [self._to_forwarding_rule(f) for
- f in v.get('forwardingRules',
- [])]
- list_forwarding_rules.extend(region_forwarding_rules)
- else:
- list_forwarding_rules = [self._to_forwarding_rule(f) for f in
- response['items']]
- return list_forwarding_rules
-
- def list_images(self, ex_project=None):
- """
- Return a list of image objects for a project.
-
- :keyword ex_project: Optional alternate project name.
- :type ex_project: ``str`` or ``None``
-
- :return: List of GCENodeImage objects
- :rtype: ``list`` of :class:`GCENodeImage`
- """
- request = '/global/images'
- if ex_project is None:
- response = self.connection.request(request, method='GET').object
- else:
- # Save the connection request_path
- save_request_path = self.connection.request_path
- # Override the connection request path
- new_request_path = save_request_path.replace(self.project,
- ex_project)
- self.connection.request_path = new_request_path
- response = self.connection.request(request, method='GET').object
- # Restore the connection request_path
- self.connection.request_path = save_request_path
- list_images = [self._to_node_image(i) for i in
- response.get('items', [])]
- return list_images
-
- def list_locations(self):
- """
- Return a list of locations (zones).
-
- The :class:`ex_list_zones` method returns more comprehensive results,
- but this is here for compatibility.
-
- :return: List of NodeLocation objects
- :rtype: ``list`` of :class:`NodeLocation`
- """
- list_locations = []
- request = '/zones'
- response = self.connection.request(request, method='GET').object
- list_locations = [self._to_node_location(l) for l in response['items']]
- return list_locations
-
- def ex_list_networks(self):
- """
- Return the list of networks.
-
- :return: A list of network objects.
- :rtype: ``list`` of :class:`GCENetwork`
- """
- list_networks = []
- request = '/global/networks'
- response = self.connection.request(request, method='GET').object
- list_networks = [self._to_network(n) for n in
- response.get('items', [])]
- return list_networks
-
- def list_nodes(self, ex_zone=None):
- """
- Return a list of nodes in the current zone or all zones.
-
- :keyword ex_zone: Optional zone name or 'all'
- :type ex_zone: ``str`` or :class:`GCEZone` or
- :class:`NodeLocation` or ``None``
-
- :return: List of Node objects
- :rtype: ``list`` of :class:`Node`
- """
- list_nodes = []
- zone = self._set_zone(ex_zone)
- if zone is None:
- request = '/aggregated/instances'
- else:
- request = '/zones/%s/instances' % (zone.name)
-
- response = self.connection.request(request, method='GET').object
-
- if 'items' in response:
- # The aggregated response returns a dict for each zone
- if zone is None:
- for v in response['items'].values():
- zone_nodes = [self._to_node(i) for i in
- v.get('instances', [])]
- list_nodes.extend(zone_nodes)
- else:
- list_nodes = [self._to_node(i) for i in response['items']]
- return list_nodes
-
- def ex_list_regions(self):
- """
- Return the list of regions.
-
- :return: A list of region objects.
- :rtype: ``list`` of :class:`GCERegion`
- """
- list_regions = []
- request = '/regions'
- response = self.connection.request(request, method='GET').object
- list_regions = [self._to_region(r) for r in response['items']]
- return list_regions
-
- def list_sizes(self, location=None):
- """
- Return a list of sizes (machineTypes) in a zone.
-
- :keyword location: Location or Zone for sizes
- :type location: ``str`` or :class:`GCEZone` or
- :class:`NodeLocation` or ``None``
-
- :return: List of GCENodeSize objects
- :rtype: ``list`` of :class:`GCENodeSize`
- """
- list_sizes = []
- zone = self._set_zone(location)
- if zone is None:
- request = '/aggregated/machineTypes'
- else:
- request = '/zones/%s/machineTypes' % (zone.name)
-
- response = self.connection.request(request, method='GET').object
-
- if 'items' in response:
- # The aggregated response returns a dict for each zone
- if zone is None:
- for v in response['items'].values():
- zone_sizes = [self._to_node_size(s) for s in
- v.get('machineTypes', [])]
- list_sizes.extend(zone_sizes)
- else:
- list_sizes = [self._to_node_size(s) for s in response['items']]
- return list_sizes
-
- def ex_list_snapshots(self):
- """
- Return the list of disk snapshots in the project.
-
- :return: A list of snapshot objects
- :rtype: ``list`` of :class:`GCESnapshot`
- """
- list_snapshots = []
- request = '/global/snapshots'
- response = self.connection.request(request, method='GET').object
- list_snapshots = [self._to_snapshot(s) for s in
- response.get('items', [])]
- return list_snapshots
-
- def ex_list_targetpools(self, region=None):
- """
- Return the list of target pools.
-
- :return: A list of target pool objects
- :rtype: ``list`` of :class:`GCETargetPool`
- """
- list_targetpools = []
- region = self._set_region(region)
- if region is None:
- request = '/aggregated/targetPools'
- else:
- request = '/regions/%s/targetPools' % (region.name)
- response = self.connection.request(request, method='GET').object
-
- if 'items' in response:
- # The aggregated result returns dictionaries for each region
- if region is None:
- for v in response['items'].values():
- region_targetpools = [self._to_targetpool(t) for t in
- v.get('targetPools', [])]
- list_targetpools.extend(region_targetpools)
- else:
- list_targetpools = [self._to_targetpool(t) for t in
- response['items']]
- return list_targetpools
-
- def list_volumes(self, ex_zone=None):
- """
- Return a list of volumes for a zone or all.
-
- Will return list from provided zone, or from the default zone unless
- given the value of 'all'.
-
- :keyword ex_zone: The zone to return volumes from.
- :type ex_zone: ``str`` or :class:`GCEZone` or
- :class:`NodeLocation` or ``None``
-
- :return: A list of volume objects.
- :rtype: ``list`` of :class:`StorageVolume`
- """
- list_volumes = []
- zone = self._set_zone(ex_zone)
- if zone is None:
- request = '/aggregated/disks'
- else:
- request = '/zones/%s/disks' % (zone.name)
-
- response = self.connection.request(request, method='GET').object
- if 'items' in response:
- # The aggregated response returns a dict for each zone
- if zone is None:
- for v in response['items'].values():
- zone_volumes = [self._to_storage_volume(d) for d in
- v.get('disks', [])]
- list_volumes.extend(zone_volumes)
- else:
- list_volumes = [self._to_storage_volume(d) for d in
- response['items']]
- return list_volumes
-
- def ex_list_zones(self):
- """
- Return the list of zones.
-
- :return: A list of zone objects.
- :rtype: ``list`` of :class:`GCEZone`
- """
- list_zones = []
- request = '/zones'
- response = self.connection.request(request, method='GET').object
- list_zones = [self._to_zone(z) for z in response['items']]
- return list_zones
-
- def ex_create_address(self, name, region=None):
- """
- Create a static address in a region.
-
- :param name: Name of static address
- :type name: ``str``
-
- :keyword region: Name of region for the address (e.g. 'us-central1')
- :type region: ``str`` or :class:`GCERegion`
-
- :return: Static Address object
- :rtype: :class:`GCEAddress`
- """
- region = region or self.region
- if not hasattr(region, 'name'):
- region = self.ex_get_region(region)
- elif region is None:
- raise ValueError('REGION_NOT_SPECIFIED',
- 'Region must be provided for an address')
- address_data = {'name': name}
- request = '/regions/%s/addresses' % (region.name)
- self.connection.async_request(request, method='POST',
- data=address_data)
- return self.ex_get_address(name, region=region)
-
- def ex_create_healthcheck(self, name, host=None, path=None, port=None,
- interval=None, timeout=None,
- unhealthy_threshold=None,
- healthy_threshold=None):
- """
- Create an Http Health Check.
-
- :param name: Name of health check
- :type name: ``str``
-
- :keyword host: Hostname of health check request. Defaults to empty
- and public IP is used instead.
- :type host: ``str``
-
- :keyword path: The request path for the check. Defaults to /.
- :type path: ``str``
-
- :keyword port: The TCP port number for the check. Defaults to 80.
- :type port: ``int``
-
- :keyword interval: How often (in seconds) to check. Defaults to 5.
- :type interval: ``int``
-
- :keyword timeout: How long to wait before failing. Defaults to 5.
- :type timeout: ``int``
-
- :keyword unhealthy_threshold: How many failures before marking
- unhealthy. Defaults to 2.
- :type unhealthy_threshold: ``int``
-
- :keyword healthy_threshold: How many successes before marking as
- healthy. Defaults to 2.
- :type healthy_threshold: ``int``
-
- :return: Health Check object
- :rtype: :class:`GCEHealthCheck`
- """
- hc_data = {}
- hc_data['name'] = name
- if host:
- hc_data['host'] = host
- # As of right now, the 'default' values aren't getting set when called
- # through the API, so set them explicitly
- hc_data['requestPath'] = path or '/'
- hc_data['port'] = port or 80
- hc_data['checkIntervalSec'] = interval or 5
- hc_data['timeoutSec'] = timeout or 5
- hc_data['unhealthyThreshold'] = unhealthy_threshold or 2
- hc_data['healthyThreshold'] = healthy_threshold or 2
-
- request = '/global/httpHealthChecks'
-
- self.connection.async_request(request, method='POST', data=hc_data)
- return self.ex_get_healthcheck(name)
-
- def ex_create_firewall(self, name, allowed, network='default',
- source_ranges=None, source_tags=None,
- target_tags=None):
- """
- Create a firewall on a network.
-
- Firewall rules should be supplied in the "allowed" field. This is a
- list of dictionaries formated like so ("ports" is optional)::
-
- [{"IPProtocol": "<protocol string or number>",
- "ports": "<port_numbers or ranges>"}]
-
- For example, to allow tcp on port 8080 and udp on all ports, 'allowed'
- would be::
-
- [{"IPProtocol": "tcp",
- "ports": ["8080"]},
- {"IPProtocol": "udp"}]
-
- See `Firewall Reference <https://developers.google.com/compute/docs/
- reference/latest/firewalls/insert>`_ for more information.
-
- :param name: Name of the firewall to be created
- :type name: ``str``
-
- :param allowed: List of dictionaries with rules
- :type allowed: ``list`` of ``dict``
-
- :keyword network: The network that the firewall applies to.
- :type network: ``str`` or :class:`GCENetwork`
-
- :keyword source_ranges: A list of IP ranges in CIDR format that the
- firewall should apply to. Defaults to
- ['0.0.0.0/0']
- :type source_ranges: ``list`` of ``str``
-
- :keyword source_tags: A list of source instance tags the rules apply
- to.
- :type source_tags: ``list`` of ``str``
-
- :keyword target_tags: A list of target instance tags the rules apply
- to.
- :type target_tags: ``list`` of ``str``
-
- :return: Firewall object
- :rtype: :class:`GCEFirewall`
- """
- firewall_data = {}
- if not hasattr(network, 'name'):
- nw = self.ex_get_network(network)
- else:
- nw = network
-
- firewall_data['name'] = name
- firewall_data['allowed'] = allowed
- firewall_data['network'] = nw.extra['selfLink']
- firewall_data['sourceRanges'] = source_ranges or ['0.0.0.0/0']
- if source_tags is not None:
- firewall_data['sourceTags'] = source_tags
- if target_tags is not None:
- firewall_data['targetTags'] = target_tags
-
- request = '/global/firewalls'
-
- self.connection.async_request(request, method='POST',
- data=firewall_data)
- return self.ex_get_firewall(name)
-
- def ex_create_forwarding_rule(self, name, targetpool, region=None,
- protocol='tcp', port_range=None,
- address=None):
- """
- Create a forwarding rule.
-
- :param name: Name of forwarding rule to be created
- :type name: ``str``
-
- :param targetpool: Target pool to apply the rule to
- :param targetpool: ``str`` or :class:`GCETargetPool`
-
- :keyword region: Region to create the forwarding rule in. Defaults to
- self.region
- :type region: ``str`` or :class:`GCERegion`
-
- :keyword protocol: Should be 'tcp' or 'udp'
- :type protocol: ``str``
-
- :keyword port_range: Optional single port number or range separated
- by a dash. Examples: '80', '5000-5999'.
- :type port_range: ``str``
-
- :keyword address: Optional static address for forwarding rule. Must be
- in same region.
- :type address: ``str`` or :class:`GCEAddress`
-
- :return: Forwarding Rule object
- :rtype: :class:`GCEForwardingRule`
- """
- forwarding_rule_data = {}
- region = region or self.region
- if not hasattr(region, 'name'):
- region = self.ex_get_region(region)
- if not hasattr(targetpool, 'name'):
- targetpool = self.ex_get_targetpool(targetpool, region)
-
- forwarding_rule_data['name'] = name
- forwarding_rule_data['region'] = region.extra['selfLink']
- forwarding_rule_data['target'] = targetpool.extra['selfLink']
- forwarding_rule_data['protocol'] = protocol.upper()
- if address:
- if not hasattr(address, 'name'):
- address = self.ex_get_address(address, region)
- forwarding_rule_data['IPAddress'] = address.extra['selfLink']
- if port_range:
- forwarding_rule_data['portRange'] = port_range
-
- request = '/regions/%s/forwardingRules' % (region.name)
-
- self.connection.async_request(request, method='POST',
- data=forwarding_rule_data)
-
- return self.ex_get_forwarding_rule(name)
-
- def ex_create_network(self, name, cidr):
- """
- Create a network.
-
- :param name: Name of network to be created
- :type name: ``str``
-
- :param cidr: Address range of network in CIDR format.
- :type cidr: ``str``
-
- :return: Network object
- :rtype: :class:`GCENetwork`
- """
- network_data = {}
- network_data['name'] = name
- network_data['IPv4Range'] = cidr
-
- request = '/global/networks'
-
- self.connection.async_request(request, method='POST',
- data=network_data)
-
- return self.ex_get_network(name)
-
- def create_node(self, name, size, image, location=None,
- ex_network='default', ex_tags=None, ex_metadata=None,
- ex_boot_disk=None, use_existing_disk=True,
- external_ip='ephemeral'):
- """
- Create a new node and return a node object for the node.
-
- :param name: The name of the node to create.
- :type name: ``str``
-
- :param size: The machine type to use.
- :type size: ``str`` or :class:`GCENodeSize`
-
- :param image: The image to use to create the node (or, if attaching
- a persistent disk, the image used to create the disk)
- :type image: ``str`` or :class:`GCENodeImage`
-
- :keyword location: The location (zone) to create the node in.
- :type location: ``str`` or :class:`NodeLocation` or
- :class:`GCEZone` or ``None``
-
- :keyword ex_network: The network to associate with the node.
- :type ex_network: ``str`` or :class:`GCENetwork`
-
- :keyword ex_tags: A list of tags to associate with the node.
- :type ex_tags: ``list`` of ``str`` or ``None``
-
- :keyword ex_metadata: Metadata dictionary for instance.
- :type ex_metadata: ``dict`` or ``None``
-
- :keyword ex_boot_disk: The boot disk to attach to the instance.
- :type ex_boot_disk: :class:`StorageVolume` or ``str``
-
- :keyword use_existing_disk: If True and if an existing disk with the
- same name/location is found, use that
- disk instead of creating a new one.
- :type use_existing_disk: ``bool``
-
- :keyword external_ip: The external IP address to use. If 'ephemeral'
- (default), a new non-static address will be
- used. If 'None', then no external address will
- be used. To use an existing static IP address,
- a GCEAddress object should be passed in.
- :type external_ip: :class:`GCEAddress` or ``str`` or None
-
- :return: A Node object for the new node.
- :rtype: :class:`Node`
- """
- location = location or self.zone
- if not hasattr(location, 'name'):
- location = self.ex_get_zone(location)
- if not hasattr(size, 'name'):
- size = self.ex_get_size(size, location)
- if not hasattr(ex_network, 'name'):
- ex_network = self.ex_get_network(ex_network)
- if not hasattr(image, 'name'):
- image = self.ex_get_image(image)
-
- if not ex_boot_disk:
- ex_boot_disk = self.create_volume(None, name, location=location,
- image=image,
- use_existing=use_existing_disk)
-
- if ex_metadata is not None:
- ex_metadata = {"items": [{"key": k, "value": v}
- for k, v in ex_metadata.items()]}
-
- request, node_data = self._create_node_req(name, size, image,
- location, ex_network,
- ex_tags, ex_metadata,
- ex_boot_disk, external_ip)
- self.connection.async_request(request, method='POST', data=node_data)
-
- return self.ex_get_node(name, location.name)
-
- def ex_create_multiple_nodes(self, base_name, size, image, number,
- location=None, ex_network='default',
- ex_tags=None, ex_metadata=None,
- ignore_errors=True, use_existing_disk=True,
- poll_interval=2, external_ip='ephemeral',
- timeout=DEFAULT_TASK_COMPLETION_TIMEOUT):
- """
- Create multiple nodes and return a list of Node objects.
-
- Nodes will be named with the base name and a number. For example, if
- the base name is 'libcloud' and you create 3 nodes, they will be
- named::
-
- libcloud-000
- libcloud-001
- libcloud-002
-
- :param base_name: The base name of the nodes to create.
- :type base_name: ``str``
-
- :param size: The machine type to use.
- :type size: ``str`` or :class:`GCENodeSize`
-
- :param image: The image to use to create the nodes.
- :type image: ``str`` or :class:`GCENodeImage`
-
- :param number: The number of nodes to create.
- :type number: ``int``
-
- :keyword location: The location (zone) to create the nodes in.
- :type location: ``str`` or :class:`NodeLocation` or
- :class:`GCEZone` or ``None``
-
- :keyword ex_network: The network to associate with the nodes.
- :type ex_network: ``str`` or :class:`GCENetwork`
-
- :keyword ex_tags: A list of tags to assiciate with the nodes.
- :type ex_tags: ``list`` of ``str`` or ``None``
-
- :keyword ex_metadata: Metadata dictionary for instances.
- :type ex_metadata: ``dict`` or ``None``
-
- :keyword ignore_errors: If True, don't raise Exceptions if one or
- more nodes fails.
- :type ignore_errors: ``bool``
-
- :keyword use_existing_disk: If True and if an existing disk with the
- same name/location is found, use that
- disk instead of creating a new one.
- :type use_existing_disk: ``bool``
-
- :keyword poll_interval: Number of seconds between status checks.
- :type poll_interval: ``int``
-
- :keyword external_ip: The external IP address to use. If 'ephemeral'
- (default), a new non-static address will be
- used. If 'None', then no external address will
- be used. (Static addresses are not supported for
- multiple node creation.)
- :type external_ip: ``str`` or None
-
- :keyword timeout: The number of seconds to wait for all nodes to be
- created before timing out.
- :type timeout: ``int``
-
- :return: A list of Node objects for the new nodes.
- :rtype: ``list`` of :class:`Node`
- """
- location = location or self.zone
- if not hasattr(location, 'name'):
- location = self.ex_get_zone(location)
- if not hasattr(size, 'name'):
- size = self.ex_get_size(size, location)
- if not hasattr(ex_network, 'name'):
- ex_network = self.ex_get_network(ex_network)
- if not hasattr(image, 'name'):
- image = self.ex_get_image(image)
-
- node_attrs = {'size': size,
- 'image': image,
- 'location': location,
- 'network': ex_network,
- 'tags': ex_tags,
- 'metadata': ex_metadata,
- 'ignore_errors': ignore_errors,
- 'use_existing_disk': use_existing_disk,
- 'external_ip': external_ip}
-
- # List for holding the status information for disk/node creation.
- status_list = []
-
- for i in range(number):
- name = '%s-%03d' % (base_name, i)
-
- status = {'name': name,
- 'node_response': None,
- 'node': None,
- 'disk_response': None,
- 'disk': None}
-
- status_list.append(status)
-
- # Create disks for nodes
- for status in status_list:
- self._multi_create_disk(status, node_attrs)
-
- start_time = time.time()
- complete = False
- while not complete:
- if (time.time() - start_time >= timeout):
- raise Exception("Timeout (%s sec) while waiting for multiple "
- "instances")
- complete = True
- time.sleep(poll_interval)
- for status in status_list:
- # If disk does not yet exist, check on its status
- if not status['disk']:
- self._multi_check_disk(status, node_attrs)
-
- # If disk exists, but node does not, create the node or check
- # on its status if already in progress.
- if status['disk'] and not status['node']:
- if not status['node_response']:
- self._multi_create_node(status, node_attrs)
- else:
- self._multi_check_node(status, node_attrs)
- # If any of the nodes have not been created (or failed) we are
- # not done yet.
- if not status['node']:
- complete = False
-
- # Return list of nodes
- node_list = []
- for status in status_list:
- node_list.append(status['node'])
- return node_list
-
- def ex_create_targetpool(self, name, region=None, healthchecks=None,
- nodes=None):
- """
- Create a target pool.
-
- :param name: Name of target pool
- :type name: ``str``
-
- :keyword region: Region to create the target pool in. Defaults to
- self.region
- :type region: ``str`` or :class:`GCERegion` or ``None``
-
- :keyword healthchecks: Optional list of health checks to attach
- :type healthchecks: ``list`` of ``str`` or :class:`GCEHealthCheck`
-
- :keyword nodes: Optional list of nodes to attach to the pool
- :type nodes: ``list`` of ``str`` or :class:`Node`
-
- :return: Target Pool object
- :rtype: :class:`GCETargetPool`
- """
- region = region or self.region
- targetpool_data = {}
- targetpool_data['name'] = name
- if not hasattr(region, 'name'):
- region = self.ex_get_region(region)
- targetpool_data['region'] = region.extra['selfLink']
-
- if healthchecks:
- if not hasattr(healthchecks[0], 'name'):
- hc_list = [self.ex_get_healthcheck(h).extra['selfLink'] for h
- in healthchecks]
- else:
- hc_list = [h.extra['selfLink'] for h in healthchecks]
- targetpool_data['healthChecks'] = hc_list
- if nodes:
- if not hasattr(nodes[0], 'name'):
- node_list = [self.ex_get_node(n, 'all').extra['selfLink'] for n
- in nodes]
- else:
- node_list = [n.extra['selfLink'] for n in nodes]
- targetpool_data['instances'] = node_list
-
- request = '/regions/%s/targetPools' % (region.name)
-
- self.connection.async_request(request, method='POST',
- data=targetpool_data)
-
- return self.ex_get_targetpool(name, region)
-
- def create_volume(self, size, name, location=None, snapshot=None,
- image=None, use_existing=True):
- """
- Create a volume (disk).
-
- :param size: Size of volume to create (in GB). Can be None if image
- or snapshot is supplied.
- :type size: ``int`` or ``str`` or ``None``
-
- :param name: Name of volume to create
- :type name: ``str``
-
- :keyword location: Location (zone) to create the volume in
- :type location: ``str`` or :class:`GCEZone` or
- :class:`NodeLocation` or ``None``
-
- :keyword snapshot: Snapshot to create image from
- :type snapshot: :class:`GCESnapshot` or ``str`` or ``None``
-
- :keyword image: Image to create disk from.
- :type image: :class:`GCENodeImage` or ``str`` or ``None``
-
- :keyword use_existing: If True and a disk with the given name already
- exists, return an object for that disk instead
- of attempting to create a new disk.
- :type use_existing: ``bool``
-
- :return: Storage Volume object
- :rtype: :class:`StorageVolume`
- """
- request, volume_data, params = self._create_vol_req(
- size, name, location, snapshot, image)
- try:
- self.connection.async_request(request, method='POST',
- data=volume_data, params=params)
- except ResourceExistsError:
- e = sys.exc_info()[1]
- if not use_existing:
- raise e
-
- return self.ex_get_volume(name, location)
-
- def create_volume_snapshot(self, volume, name):
- """
- Create a snapshot of the provided Volume.
-
- :param volume: A StorageVolume object
- :type volume: :class:`StorageVolume`
-
- :return: A GCE Snapshot object
- :rtype: :class:`GCESnapshot`
- """
- snapshot_data = {}
- snapshot_data['name'] = name
- request = '/zones/%s/disks/%s/createSnapshot' % (
- volume.extra['zone'].name, volume.name)
- self.connection.async_request(request, method='POST',
- data=snapshot_data)
-
- return self.ex_get_snapshot(name)
-
- def list_volume_snapshots(self, volume):
- """
- List snapshots created from the provided volume.
-
- For GCE, snapshots are global, but while the volume they were
- created from still exists, the source disk for the snapshot is
- tracked.
-
- :param volume: A StorageVolume object
- :type volume: :class:`StorageVolume`
-
- :return: A list of Snapshot objects
- :rtype: ``list`` of :class:`GCESnapshot`
- """
- volume_snapshots = []
- volume_link = volume.extra['selfLink']
- all_snapshots = self.ex_list_snapshots()
- for snapshot in all_snapshots:
- if snapshot.extra['sourceDisk'] == volume_link:
- volume_snapshots.append(snapshot)
- return volume_snapshots
-
- def ex_update_healthcheck(self, healthcheck):
- """
- Update a health check with new values.
-
- To update, change the attributes of the health check object and pass
- the updated object to the method.
-
- :param healthcheck: A healthcheck object with updated values.
- :type healthcheck: :class:`GCEHealthCheck`
-
- :return: An object representing the new state of the health check.
- :rtype: :class:`GCEHealthCheck`
- """
- hc_data = {}
- hc_data['name'] = healthcheck.name
- hc_data['requestPath'] = healthcheck.path
- hc_data['port'] = healthcheck.port
- hc_data['checkIntervalSec'] = healthcheck.interval
- hc_data['timeoutSec'] = healthcheck.timeout
- hc_data['unhealthyThreshold'] = healthcheck.unhealthy_threshold
- hc_data['healthyThreshold'] = healthcheck.healthy_threshold
- if healthcheck.extra['host']:
- hc_data['host'] = healthcheck.extra['host']
- if healthcheck.extra['description']:
- hc_data['description'] = healthcheck.extra['description']
-
- request = '/global/httpHealthChecks/%s' % (healthcheck.name)
-
- self.connection.async_request(request, method='PUT',
- data=hc_data)
-
- return self.ex_get_healthcheck(healthcheck.name)
-
- def ex_update_firewall(self, firewall):
- """
- Update a firewall with new values.
-
- To update, change the attributes of the firewall object and pass the
- updated object to the method.
-
- :param firewall: A firewall object with updated values.
- :type firewall: :class:`GCEFirewall`
-
- :return: An object representing the new state of the firewall.
- :rtype: :class:`GCEFirewall`
- """
- firewall_data = {}
- firewall_data['name'] = firewall.name
- firewall_data['allowed'] = firewall.allowed
- firewall_data['network'] = firewall.network.extra['selfLink']
- if firewall.source_ranges:
- firewall_data['sourceRanges'] = firewall.source_ranges
- if firewall.source_tags:
- firewall_data['sourceTags'] = firewall.source_tags
- if firewall.target_tags:
- firewall_data['targetTags'] = firewall.target_tags
- if firewall.extra['description']:
- firewall_data['description'] = firewall.extra['description']
-
- request = '/global/firewalls/%s' % (firewall.name)
-
- self.connection.async_request(request, method='PUT',
- data=firewall_data)
-
- return self.ex_get_firewall(firewall.name)
-
- def ex_targetpool_add_node(self, targetpool, node):
- """
- Add a node to a target pool.
-
- :param targetpool: The targetpool to add node to
- :type targetpool: ``str`` or :class:`GCETargetPool`
-
- :param node: The node to add
- :type node: ``str`` or :class:`Node`
-
- :returns: True if successful
- :rtype: ``bool``
- """
- if not hasattr(targetpool, 'name'):
- targetpool = self.ex_get_targetpool(targetpool)
- if not hasattr(node, 'name'):
- node = self.ex_get_node(node, 'all')
-
- targetpool_data = {'instances': [{'instance': node.extra['selfLink']}]}
-
- request = '/regions/%s/targetPools/%s/addInstance' % (
- targetpool.region.name, targetpool.name)
- self.connection.async_request(request, method='POST',
- data=targetpool_data)
- targetpool.nodes.append(node)
- return True
-
- def ex_targetpool_add_healthcheck(self, targetpool, healthcheck):
- """
- Add a health check to a target pool.
-
- :param targetpool: The targetpool to add health check to
- :type targetpool: ``str`` or :class:`GCETargetPool`
-
- :param healthcheck: The healthcheck to add
- :type healthcheck: ``str`` or :class:`GCEHealthCheck`
-
- :returns: True if successful
- :rtype: ``bool``
- """
- if not hasattr(targetpool, 'name'):
- targetpool = self.ex_get_targetpool(targetpool)
- if not hasattr(healthcheck, 'name'):
- healthcheck = self.ex_get_healthcheck(healthcheck)
-
- targetpool_data = {'healthCheck': healthcheck.extra['selfLink']}
-
- request = '/regions/%s/targetPools/%s/addHealthCheck' % (
- targetpool.region.name, targetpool.name)
- self.connection.async_request(request, method='POST',
- data=targetpool_data)
- targetpool.healthchecks.append(healthcheck)
- return True
-
- def ex_targetpool_remove_node(self, targetpool, node):
- """
- Remove a node from a target pool.
-
- :param targetpool: The targetpool to remove node from
- :type targetpool: ``str`` or :class:`GCETargetPool`
-
- :param node: The node to remove
- :type node: ``str`` or :class:`Node`
-
- :returns: True if successful
- :rtype: ``bool``
- """
- if not hasattr(targetpool, 'name'):
- targetpool = self.ex_get_targetpool(targetpool)
- if not hasattr(node, 'name'):
- node = self.ex_get_node(node, 'all')
-
- targetpool_data = {'instances': [{'instance': node.extra['selfLink']}]}
-
- request = '/regions/%s/targetPools/%s/removeInstance' % (
- targetpool.region.name, targetpool.name)
- self.connection.async_request(request, method='POST',
- data=targetpool_data)
- # Remove node object from node list
- index = None
- for i, nd in enumerate(targetpool.nodes):
- if nd.name == node.name:
- index = i
- break
- if index is not None:
- targetpool.nodes.pop(index)
- return True
-
- def ex_targetpool_remove_healthcheck(self, targetpool, healthcheck):
- """
- Remove a health check from a target pool.
-
- :param targetpool: The targetpool to remove health check from
- :type targetpool: ``str`` or :class:`GCETargetPool`
-
- :param healthcheck: The healthcheck to remove
- :type healthcheck: ``str`` or :class:`GCEHealthCheck`
-
- :returns: True if successful
- :rtype: ``bool``
- """
- if not hasattr(targetpool, 'name'):
- targetpool = self.ex_get_targetpool(targetpool)
- if not hasattr(healthcheck, 'name'):
- healthcheck = self.ex_get_healthcheck(healthcheck)
-
- targetpool_data = {'healthCheck': healthcheck.extra['selfLink']}
-
- request = '/regions/%s/targetPools/%s/removeHealthCheck' % (
- targetpool.region.name, targetpool.name)
- self.connection.async_request(request, method='POST',
- data=targetpool_data)
- # Remove healthcheck object from healthchecks list
- index = None
- for i, hc in enumerate(targetpool.healthchecks):
- if hc.name == healthcheck.name:
- index = i
- if index is not None:
- targetpool.healthchecks.pop(index)
- return True
-
- def reboot_node(self, node):
- """
- Reboot a node.
-
- :param node: Node to be rebooted
- :type node: :class:`Node`
-
- :return: True if successful, False if not
- :rtype: ``bool``
- """
- request = '/zones/%s/instances/%s/reset' % (node.extra['zone'].name,
- node.name)
- self.connection.async_request(request, method='POST',
- data='ignored')
- return True
-
- def ex_set_node_tags(self, node, tags):
- """
- Set the tags on a Node instance.
-
- Note that this updates the node object directly.
-
- :param node: Node object
- :type node: :class:`Node`
-
- :param tags: List of tags to apply to the object
- :type tags: ``list`` of ``str``
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/zones/%s/instances/%s/setTags' % (node.extra['zone'].name,
- node.name)
-
- tags_data = {}
- tags_data['items'] = tags
- tags_data['fingerprint'] = node.extra['tags_fingerprint']
-
- self.connection.async_request(request, method='POST',
- data=tags_data)
- new_node = self.ex_get_node(node.name, node.extra['zone'])
- node.extra['tags'] = new_node.extra['tags']
- node.extra['tags_fingerprint'] = new_node.extra['tags_fingerprint']
- return True
-
- def ex_set_node_scheduling(self, node, on_host_maintenance=None,
- automatic_restart=None):
- """Set the maintenance behavior for the node.
-
- See `Scheduling <https://developers.google.com/compute/
- docs/instances#onhostmaintenance>`_ documentation for more info.
-
- :param node: Node object
- :type node: :class:`Node`
-
- :keyword on_host_maintenance: Defines whether node should be
- terminated or migrated when host machine
- goes down. Acceptable values are:
- 'MIGRATE' or 'TERMINATE' (If not
- supplied, value will be reset to GCE
- default value for the instance type.)
- :type on_host_maintenance: ``str``
-
- :keyword automatic_restart: Defines whether the instance should be
- automatically restarted when it is
- terminated by Compute Engine. (If not
- supplied, value will be set to the GCE
- default value for the instance type.)
- :type automatic_restart: ``bool``
-
- :return: True if successful.
- :rtype: ``bool``
- """
- if not hasattr(node, 'name'):
- node = self.ex_get_node(node, 'all')
- if on_host_maintenance is not None:
- on_host_maintenance = on_host_maintenance.upper()
- ohm_values = ['MIGRATE', 'TERMINATE']
- if on_host_maintenance not in ohm_values:
- raise ValueError('on_host_maintenance must be one of %s' %
- ','.join(ohm_values))
-
- request = '/zones/%s/instances/%s/setScheduling' % (
- node.extra['zone'].name, node.name)
-
- scheduling_data = {}
- if on_host_maintenance is not None:
- scheduling_data['onHostMaintenance'] = on_host_maintenance
- if automatic_restart is not None:
- scheduling_data['automaticRestart'] = automatic_restart
-
- self.connection.async_request(request, method='POST',
- data=scheduling_data)
-
- new_node = self.ex_get_node(node.name, node.extra['zone'])
- node.extra['scheduling'] = new_node.extra['scheduling']
-
- ohm = node.extra['scheduling'].get('onHostMaintenance')
- ar = node.extra['scheduling'].get('automaticRestart')
-
- success = True
- if on_host_maintenance not in [None, ohm]:
- success = False
- if automatic_restart not in [None, ar]:
- success = False
-
- return success
-
- def deploy_node(self, name, size, image, script, location=None,
- ex_network='default', ex_tags=None):
- """
- Create a new node and run a script on start-up.
-
- :param name: The name of the node to create.
- :type name: ``str``
-
- :param size: The machine type to use.
- :type size: ``str`` or :class:`GCENodeSize`
-
- :param image: The image to use to create the node.
- :type image: ``str`` or :class:`GCENodeImage`
-
- :param script: File path to start-up script
- :type script: ``str``
-
- :keyword location: The location (zone) to create the node in.
- :type location: ``str`` or :class:`NodeLocation` or
- :class:`GCEZone` or ``None``
-
- :keyword ex_network: The network to associate with the node.
- :type ex_network: ``str`` or :class:`GCENetwork`
-
- :keyword ex_tags: A list of tags to associate with the node.
- :type ex_tags: ``list`` of ``str`` or ``None``
-
- :return: A Node object for the new node.
- :rtype: :class:`Node`
- """
- with open(script, 'r') as f:
- script_data = f.read()
- metadata = {'items': [{'key': 'startup-script',
- 'value': script_data}]}
-
- return self.create_node(name, size, image, location=location,
- ex_network=ex_network, ex_tags=ex_tags,
- ex_metadata=metadata)
-
- def attach_volume(self, node, volume, device=None, ex_mode=None,
- ex_boot=False):
- """
- Attach a volume to a node.
-
- If volume is None, a scratch disk will be created and attached.
-
- :param node: The node to attach the volume to
- :type node: :class:`Node`
-
- :param volume: The volume to attach. If none, a scratch disk will be
- attached.
- :type volume: :class:`StorageVolume` or ``None``
-
- :keyword device: The device name to attach the volume as. Defaults to
- volume name.
- :type device: ``str``
-
- :keyword ex_mode: Either 'READ_WRITE' or 'READ_ONLY'
- :type ex_mode: ``str``
-
- :keyword ex_boot: If true, disk will be attached as a boot disk
- :type ex_boot: ``bool``
-
- :return: True if successful
- :rtype: ``bool``
- """
- volume_data = {}
- if volume is None:
- volume_data['type'] = 'SCRATCH'
- else:
- volume_data['type'] = 'PERSISTENT'
- volume_data['source'] = volume.extra['selfLink']
- volume_data['kind'] = 'compute#attachedDisk'
- volume_data['mode'] = ex_mode or 'READ_WRITE'
-
- if device:
- volume_data['deviceName'] = device
- else:
- volume_data['deviceName'] = volume.name
-
- volume_data['boot'] = ex_boot
-
- request = '/zones/%s/instances/%s/attachDisk' % (
- node.extra['zone'].name, node.name)
- self.connection.async_request(request, method='POST',
- data=volume_data)
- return True
-
- def detach_volume(self, volume, ex_node=None):
- """
- Detach a volume from a node.
-
- :param volume: Volume object to detach
- :type volume: :class:`StorageVolume`
-
- :keyword ex_node: Node object to detach volume from (required)
- :type ex_node: :class:`Node`
-
- :return: True if successful
- :rtype: ``bool``
- """
- if not ex_node:
- return False
- request = '/zones/%s/instances/%s/detachDisk?deviceName=%s' % (
- ex_node.extra['zone'].name, ex_node.name, volume.name)
-
- self.connection.async_request(request, method='POST',
- data='ignored')
- return True
-
- def ex_set_volume_auto_delete(self, volume, node, auto_delete=True):
- """
- Sets the auto-delete flag for a volume attached to a node.
-
- :param volume: Volume object to auto-delete
- :type volume: :class:`StorageVolume`
-
- :param ex_node: Node object to auto-delete volume from
- :type ex_node: :class:`Node`
-
- :keyword auto_delete: Flag to set for the auto-delete value
- :type auto_delete: ``bool`` (default True)
-
- :return: True if successfull
- :rtype: ``bool``
- """
- request = '/zones/%s/instances/%s/setDiskAutoDelete' % (
- node.extra['zone'].name, node.name
- )
- delete_params = {
- 'deviceName': volume,
- 'autoDelete': auto_delete,
- }
- self.connection.async_request(request, method='POST',
- params=delete_params)
- return True
-
- def ex_destroy_address(self, address):
- """
- Destroy a static address.
-
- :param address: Address object to destroy
- :type address: :class:`GCEAddress`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/regions/%s/addresses/%s' % (address.region.name,
- address.name)
-
- self.connection.async_request(request, method='DELETE')
- return True
-
- def ex_delete_image(self, image):
- """
- Delete a specific image resource.
-
- :param image: Image object to delete
- :type image: ``str`` or :class:`GCENodeImage`
-
- :return: True if successfull
- :rtype: ``bool``
- """
- if not hasattr(image, 'name'):
- image = self.ex_get_image(image)
-
- request = '/global/images/%s' % (image.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def ex_deprecate_image(self, image, replacement, state=None):
- """
- Deprecate a specific image resource.
-
- :param image: Image object to deprecate
- :type image: ``str`` or :class: `GCENodeImage`
-
- :param replacement: Image object to use as a replacement
- :type replacement: ``str`` or :class: `GCENodeImage`
-
- :param state: State of the image
- :type state: ``str``
-
- :return: True if successfull
- :rtype: ``bool``
- """
- if not hasattr(image, 'name'):
- image = self.ex_get_image(image)
-
- if not hasattr(replacement, 'name'):
- replacement = self.ex_get_image(replacement)
-
- if state is None:
- state = 'DEPRECATED'
-
- possible_states = ['DELETED', 'DEPRECATED', 'OBSOLETE']
-
- if state not in possible_states:
- raise ValueError('state must be one of %s'
- % ','.join(possible_states))
-
- image_data = {
- 'state': state,
- 'replacement': replacement.extra['selfLink'],
- }
-
- request = '/global/images/%s/deprecate' % (image.name)
-
- self.connection.request(
- request, method='POST', data=image_data).object
-
- return True
-
- def ex_destroy_healthcheck(self, healthcheck):
- """
- Destroy a healthcheck.
-
- :param healthcheck: Health check object to destroy
- :type healthcheck: :class:`GCEHealthCheck`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/global/httpHealthChecks/%s' % (healthcheck.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def ex_destroy_firewall(self, firewall):
- """
- Destroy a firewall.
-
- :param firewall: Firewall object to destroy
- :type firewall: :class:`GCEFirewall`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/global/firewalls/%s' % (firewall.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def ex_destroy_forwarding_rule(self, forwarding_rule):
- """
- Destroy a forwarding rule.
-
- :param forwarding_rule: Forwarding Rule object to destroy
- :type forwarding_rule: :class:`GCEForwardingRule`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/regions/%s/forwardingRules/%s' % (
- forwarding_rule.region.name, forwarding_rule.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def ex_destroy_network(self, network):
- """
- Destroy a network.
-
- :param network: Network object to destroy
- :type network: :class:`GCENetwork`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/global/networks/%s' % (network.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def destroy_node(self, node, destroy_boot_disk=False):
- """
- Destroy a node.
-
- :param node: Node object to destroy
- :type node: :class:`Node`
-
- :keyword destroy_boot_disk: If true, also destroy the node's
- boot disk. (Note that this keyword is not
- accessible from the node's .destroy()
- method.)
- :type destroy_boot_disk: ``bool``
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/zones/%s/instances/%s' % (node.extra['zone'].name,
- node.name)
- self.connection.async_request(request, method='DELETE')
- if destroy_boot_disk and node.extra['boot_disk']:
- node.extra['boot_disk'].destroy()
- return True
-
- def ex_destroy_multiple_nodes(self, node_list, ignore_errors=True,
- destroy_boot_disk=False, poll_interval=2,
- timeout=DEFAULT_TASK_COMPLETION_TIMEOUT):
- """
- Destroy multiple nodes at once.
-
- :param node_list: List of nodes to destroy
- :type node_list: ``list`` of :class:`Node`
-
- :keyword ignore_errors: If true, don't raise an exception if one or
- more nodes fails to be destroyed.
- :type ignore_errors: ``bool``
-
- :keyword destroy_boot_disk: If true, also destroy the nodes' boot
- disks.
- :type destroy_boot_disk: ``bool``
-
- :keyword poll_interval: Number of seconds between status checks.
- :type poll_interval: ``int``
-
- :keyword timeout: Number of seconds to wait for all nodes to be
- destroyed.
- :type timeout: ``int``
-
- :return: A list of boolean values. One for each node. True means
- that the node was successfully destroyed.
- :rtype: ``list`` of ``bool``
- """
- status_list = []
- complete = False
- start_time = time.time()
- for node in node_list:
- request = '/zones/%s/instances/%s' % (node.extra['zone'].name,
- node.name)
- try:
- response = self.connection.request(request,
- method='DELETE').object
- except GoogleBaseError:
- self._catch_error(ignore_errors=ignore_errors)
- response = None
-
- status = {'node': node,
- 'node_success': False,
- 'node_response': response,
- 'disk_success': not destroy_boot_disk,
- 'disk_response': None}
-
- status_list.append(status)
-
- while not complete:
- if (time.time() - start_time >= timeout):
- raise Exception("Timeout (%s sec) while waiting to delete "
- "multiple instances")
- complete = True
- for status in status_list:
- # If one of the operations is running, check the status
- operation = status['node_response'] or status['disk_response']
- delete_disk = False
- if operation:
- no_errors = True
- try:
- response = self.connection.request(
- operation['selfLink']).object
- except GoogleBaseError:
- self._catch_error(ignore_errors=ignore_errors)
- no_errors = False
- response = {'status': 'DONE'}
- if response['status'] == 'DONE':
- # If a node was deleted, update status and indicate
- # that the disk is ready to be deleted.
- if status['node_response']:
- status['node_response'] = None
- status['node_success'] = no_errors
- delete_disk = True
- else:
- status['disk_response'] = None
- status['disk_success'] = no_errors
- # If we are destroying disks, and the node has been deleted,
- # destroy the disk.
- if delete_disk and destroy_boot_disk:
- boot_disk = status['node'].extra['boot_disk']
- if boot_disk:
- request = '/zones/%s/disks/%s' % (
- boot_disk.extra['zone'].name, boot_disk.name)
- try:
- response = self.connection.request(
- request, method='DELETE').object
- except GoogleBaseError:
- self._catch_error(ignore_errors=ignore_errors)
- no_errors = False
- response = None
- status['disk_response'] = response
- else: # If there is no boot disk, ignore
- status['disk_success'] = True
- operation = status['node_response'] or status['disk_response']
- if operation:
- time.sleep(poll_interval)
- complete = False
-
- success = []
- for status in status_list:
- s = status['node_success'] and status['disk_success']
- success.append(s)
- return success
-
- def ex_destroy_targetpool(self, targetpool):
- """
- Destroy a target pool.
-
- :param targetpool: TargetPool object to destroy
- :type targetpool: :class:`GCETargetPool`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/regions/%s/targetPools/%s' % (targetpool.region.name,
- targetpool.name)
-
- self.connection.async_request(request, method='DELETE')
- return True
-
- def destroy_volume(self, volume):
- """
- Destroy a volume.
-
- :param volume: Volume object to destroy
- :type volume: :class:`StorageVolume`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/zones/%s/disks/%s' % (volume.extra['zone'].name,
- volume.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def destroy_volume_snapshot(self, snapshot):
- """
- Destroy a snapshot.
-
- :param snapshot: Snapshot object to destroy
- :type snapshot: :class:`GCESnapshot`
-
- :return: True if successful
- :rtype: ``bool``
- """
- request = '/global/snapshots/%s' % (snapshot.name)
- self.connection.async_request(request, method='DELETE')
- return True
-
- def ex_get_address(self, name, region=None):
- """
- Return an Address object based on an address name and optional region.
-
- :param name: The name of the address
- :type name: ``str``
-
- :keyword region: The region to search for the address in (set to
- 'all' to search all regions)
- :type region: ``str`` :class:`GCERegion` or ``None``
-
- :return: An Address object for the address
- :rtype: :class:`GCEAddress`
- """
- region = self._set_region(region) or self._find_zone_or_region(
- name, 'addresses', region=True, res_name='Address')
- request = '/regions/%s/addresses/%s' % (region.name, name)
- response = self.connection.request(request, method='GET').object
- return self._to_address(response)
-
- def ex_get_healthcheck(self, name):
- """
- Return a HealthCheck object based on the healthcheck name.
-
- :param name: The name of the healthcheck
- :type name: ``str``
-
- :return: A GCEHealthCheck object
- :rtype: :class:`GCEHealthCheck`
- """
- request = '/global/httpHealthChecks/%s' % (name)
- response = self.connection.request(request, method='GET').object
- return self._to_healthcheck(response)
-
- def ex_get_firewall(self, name):
- """
- Return a Firewall object based on the firewall name.
-
- :param name: The name of the firewall
- :type name: ``str``
-
- :return: A GCEFirewall object
- :rtype: :class:`GCEFirewall`
- """
- request = '/global/firewalls/%s' % (name)
- response = self.connection.request(request, method='GET').object
- return self._to_firewall(response)
-
- def ex_get_forwarding_rule(self, name, region=None):
- """
- Return a Forwarding Rule object based on the forwarding rule name.
-
- :param name: The name of the forwarding rule
- :type name: ``str``
-
- :keyword region: The region to search for the rule in (set to 'all'
- to search all regions).
- :type region: ``str`` or ``None``
-
- :return: A GCEForwardingRule object
- :rtype: :class:`GCEForwardingRule`
- """
- region = self._set_region(region) or self._find_zone_or_region(
- name, 'forwardingRules', region=True, res_name='ForwardingRule')
- request = '/regions/%s/forwardingRules/%s' % (region.name, name)
- response = self.connection.request(request, method='GET').object
- return self._to_forwarding_rule(response)
-
- def ex_get_image(self, partial_name):
- """
- Return an GCENodeImage object based on the name or link provided.
-
- :param partial_name: The name, partial name, or full path of a GCE
- image.
- :type partial_name: ``str``
-
- :return: GCENodeImage object based on provided information or None if
- an image with that name is not found.
- :rtype: :class:`GCENodeImage` or ``None``
- """
- if partial_name.startswith('https://'):
- response = self.connection.request(partial_name, method='GET')
- return self._to_node_image(response.object)
- image = self._match_images(None, partial_name)
- if not image:
- if (partial_name.startswith('debian') or
- partial_name.startswith('backports')):
- image = self._match_images('debian-cloud', partial_name)
- elif partial_name.startswith('centos'):
- image = self._match_images('centos-cloud', partial_name)
- elif partial_name.startswith('sles'):
- image = self._match_images('suse-cloud', partial_name)
- elif partial_name.startswith('rhel'):
- image = self._match_images('rhel-cloud', partial_name)
- elif partial_name.startswith('windows'):
- image = self._match_images('windows-cloud', partial_name)
- elif partial_name.startswith('container-vm'):
- image = self._match_images('google-containers', partial_name)
-
- return image
-
- def ex_get_network(self, name):
- """
- Return a Network object based on a network name.
-
- :param name: The name of the network
- :type name: ``str``
-
- :return: A Network object for the network
- :rtype: :class:`GCENetwork`
- """
- request = '/global/networks/%s' % (name)
- response = self.connection.request(request, method='GET').object
- return self._to_network(response)
-
- def ex_get_node(self, name, zone=None):
- """
- Return a Node object based on a node name and optional zone.
-
- :param name: The name of the node
- :type name: ``str``
-
- :keyword zone: The zone to search for the node in. If set to 'all',
- search all zones for the instance.
- :type zone: ``str`` or :class:`GCEZone` or
- :class:`No
<TRUNCATED>
[2/2] git commit: Remove duplicated file.
Posted by to...@apache.org.
Remove duplicated file.
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/07538350
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/07538350
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/07538350
Branch: refs/heads/trunk
Commit: 075383509e507f88b2c105b4f5fde5b4d4af5e68
Parents: feea74d
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Jul 21 15:52:19 2014 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Jul 21 15:52:49 2014 +0200
----------------------------------------------------------------------
libcloud/compute/drivers/gce.py.orig | 3353 -----------------------------
1 file changed, 3353 deletions(-)
----------------------------------------------------------------------