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

Service-specific zones in OpenStack

almahmoud 7 лет назад
Родитель
Сommit
4ea1491af9

+ 33 - 0
cloudbridge/providers/openstack/provider.py

@@ -48,6 +48,18 @@ class OpenStackCloudProvider(BaseCloudProvider):
             'os_region_name', get_env('OS_REGION_NAME'))
         self._zone_name = self._get_config_value(
             'os_zone_name', get_env('OS_ZONE_NAME'))
+        self._compute_zone_name = self._get_config_value(
+            'os_compute_zone_name', get_env('OS_COMPUTE_ZONE_NAME',
+                                            self.zone_name))
+        self._networking_zone_name = self._get_config_value(
+            'os_networking_zone_name', get_env('OS_NETWORKING_ZONE_NAME',
+                                               self.zone_name))
+        self._security_zone_name = self._get_config_value(
+            'os_security_zone_name', get_env('OS_SECURITY_ZONE_NAME',
+                                             self.zone_name))
+        self._storage_zone_name = self._get_config_value(
+            'os_storage_zone_name', get_env('OS_STORAGE_ZONE_NAME',
+                                            self.zone_name))
         self.project_domain_name = self._get_config_value(
             'os_project_domain_name',
             get_env('OS_PROJECT_DOMAIN_NAME'))
@@ -320,3 +332,24 @@ class OpenStackCloudProvider(BaseCloudProvider):
         return neutron_client.Client(auth_url=self.auth_url,
                                      session=self._keystone_session,
                                      region_name=self.region_name)
+
+    @property
+    def zone_name(self):
+        if not self._zone_name:
+            region = self.compute.regions.get(self.region_name)
+            zone = next(iter(region.zones))
+            self._zone_name = zone.name if zone else None
+        return self._zone_name
+
+    def service_zone_name(self, service):
+        service_name = service._service_event_pattern
+        if "networking" in service_name and self._networking_zone_name:
+            return self._networking_zone_name
+        elif "security" in service_name and self._security_zone_name:
+            return self._security_zone_name
+        elif "compute" in service_name and self._compute_zone_name:
+            return self._compute_zone_name
+        elif "storage" in service_name and self._storage_zone_name:
+            return self._storage_zone_name
+        else:
+            return self.zone_name

+ 20 - 14
cloudbridge/providers/openstack/services.py

@@ -373,12 +373,12 @@ class OpenStackVolumeService(BaseVolumeService):
         except CinderNotFound:
             log.debug("Volume %s was not found.", volume_id)
             return None
-        if os_vol.availability_zone != self.provider.zone_name:
+        if os_vol.availability_zone != self.provider.service_zone_name(self):
             log.debug("Volume %s was found in availability zone '%s' while the"
                       " OpenStack provider is in zone '%s'",
                       volume_id,
                       os_vol.availability_zone,
-                      self.provider.zone_name)
+                      self.provider.service_zone_name(self))
             return None
         else:
             return OpenStackVolume(self.provider, os_vol)
@@ -396,7 +396,8 @@ class OpenStackVolumeService(BaseVolumeService):
 
         log.debug("Searching for an OpenStack Volume with the label %s", label)
         search_opts = {'name': label,
-                       'availability_zone': self.provider.zone_name}
+                       'availability_zone':
+                           self.provider.service_zone_name(self)}
         cb_vols = [
             OpenStackVolume(self.provider, vol)
             for vol in self.provider.cinder.volumes.list(
@@ -409,7 +410,8 @@ class OpenStackVolumeService(BaseVolumeService):
     @dispatch(event="provider.storage.volumes.list",
               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
     def list(self, limit=None, marker=None):
-        search_opts = {'availability_zone': self.provider.zone_name}
+        search_opts = {'availability_zone': self.provider
+                                                .service_zone_name(self)}
         cb_vols = [
             OpenStackVolume(self.provider, vol)
             for vol in self.provider.cinder.volumes.list(
@@ -423,7 +425,7 @@ class OpenStackVolumeService(BaseVolumeService):
               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
     def create(self, label, size, snapshot=None, description=None):
         OpenStackVolume.assert_valid_resource_label(label)
-        zone_name = self.provider.zone_name
+        zone_name = self.provider.service_zone_name(self)
         snapshot_id = snapshot.id if isinstance(
             snapshot, OpenStackSnapshot) and snapshot else snapshot
 
@@ -782,7 +784,7 @@ class OpenStackInstanceService(BaseInstanceService):
             net_id = (self.provider.networking.subnets
                       .get(subnet_id).network_id
                       if subnet_id else None)
-        zone_name = self.provider.zone_name
+        zone_name = self.provider.service_zone_name(self)
         key_pair_name = key_pair.name if \
             isinstance(key_pair, KeyPair) else key_pair
         bdm = None
@@ -858,7 +860,8 @@ class OpenStackInstanceService(BaseInstanceService):
                 "attributes: %s" % (kwargs, 'label'))
 
         search_opts = {'name': label,
-                       'availability_zone': self.provider.zone_name}
+                       'availability_zone': self.provider
+                                                .service_zone_name(self)}
         cb_insts = [
             OpenStackInstance(self.provider, inst)
             for inst in self.provider.nova.servers.list(
@@ -873,7 +876,8 @@ class OpenStackInstanceService(BaseInstanceService):
         """
         List all instances.
         """
-        search_opts = {'availability_zone': self.provider.zone_name}
+        search_opts = {'availability_zone': self.provider
+                                                .service_zone_name(self)}
         cb_insts = [
             OpenStackInstance(self.provider, inst)
             for inst in self.provider.nova.servers.list(
@@ -895,12 +899,12 @@ class OpenStackInstanceService(BaseInstanceService):
             return None
         if (getattr(os_instance,
                     'OS-EXT-AZ:availability_zone', "")
-                != self.provider.zone_name):
+                != self.provider.service_zone_name(self)):
             log.debug("Instance %s was found in availability zone '%s' while "
                       "the OpenStack provider is in zone '%s'",
                       instance_id,
                       getattr(os_instance, 'OS-EXT-AZ:availability_zone', ""),
-                      self.provider.zone_name)
+                      self.provider.service_zone_name(self))
             return None
         return OpenStackInstance(self.provider, os_instance)
 
@@ -1030,7 +1034,7 @@ class OpenStackNetworkService(BaseNetworkService):
                     # If there are no availability zones, keep the network
                     # in the results list
                     and (not network.get('availability_zones')
-                         or self.provider.zone_name
+                         or self.provider.service_zone_name(self)
                          in network.get('availability_zones'))]
         return ClientPagedResultList(self.provider, networks,
                                      limit=limit, marker=marker)
@@ -1151,12 +1155,13 @@ class OpenStackRouterService(BaseRouterService):
         if not router:
             log.debug("Router %s was not found.", router_id)
             return None
-        elif self.provider.zone_name not in router.availability_zones:
+        elif self.provider.service_zone_name(self) \
+                not in router.availability_zones:
             log.debug("Router %s was found in availability zone '%s' while the"
                       " OpenStack provider is in zone '%s'",
                       router_id,
                       router.availability_zones,
-                      self.provider.zone_name)
+                      self.provider.service_zone_name(self))
             return None
         return OpenStackRouter(self.provider, router)
 
@@ -1165,7 +1170,8 @@ class OpenStackRouterService(BaseRouterService):
     def list(self, limit=None, marker=None):
         routers = self.provider.os_conn.list_routers()
         os_routers = [OpenStackRouter(self.provider, r) for r in routers
-                      if self.provider.zone_name in r.availability_zones]
+                      if self.provider.service_zone_name(self)
+                      in r.availability_zones]
         return ClientPagedResultList(self.provider, os_routers, limit=limit,
                                      marker=marker)
 

+ 61 - 1
docs/topics/setup.rst

@@ -167,6 +167,54 @@ GCP
 |                         | Refer to the GCP python sdk for available options.                     |
 +-------------------------+------------------------------------------------------------------------+
 
+OpenStack
+~~~~~~~~~
+
++-------------------------+--------------------------------------------------------------+
+| Variable                | Description                                                  |
++=========================+==============================================================+
+| os_auth_url             | Required. OpenStack authentication endpoint.                 |
+|                         | eg: https://my-openstack.com:5000/v3                         |
++-------------------------+--------------------------------------------------------------+
+| os_username             | Required. Username for authentication.                       |
++-------------------------+--------------------------------------------------------------+
+| os_password             | Required. password for authentication.                       |
++-------------------------+--------------------------------------------------------------+
+| os_project_name         | Required. The project in which to manage resources.          |
++-------------------------+--------------------------------------------------------------+
+| os_region_name          | Required. Region in which to manage resources.               |
++-------------------------+--------------------------------------------------------------+
+| os_zone_name            | Default Availability Zone in which to manage resources.      |
+|                         | If not provided, will default to the first available zone    |
+|                         | in the region. This zone will be the default for all services|
+|                         | unless overwritten by service-specific zone configs          |
++-------------------------+--------------------------------------------------------------+
+| os_compute_zone_name    | Default Availability Zone for Compute servies.               |
+|                         | If not provided, will default to `os_zone_name`              |
++-------------------------+--------------------------------------------------------------+
+| os_networking_zone_name | Default Availability Zone for Networking servies.            |
+|                         | If not provided, will default to `os_zone_name`              |
++-------------------------+--------------------------------------------------------------+
+| os_security_zone_name   | Default Availability Zone for Security servies.              |
+|                         | If not provided, will default to `os_zone_name`              |
++-------------------------+--------------------------------------------------------------+
+| os_storage_zone_name    | Default Availability Zone for Storage servies.               |
+|                         | If not provided, will default to `os_zone_name`              |
++-------------------------+--------------------------------------------------------------+
+| nova_service_name       | Service name for the NOVA client.                            |
++-------------------------+--------------------------------------------------------------+
+| os_auth_token           | Authentication token, if applicable.                         |
++-------------------------+--------------------------------------------------------------+
+| os_compute_api_version  | Compute API version, if applicable.                          |
++-------------------------+--------------------------------------------------------------+
+| os_volume_api_version   | Volume API version, if applicable.                           |
++-------------------------+--------------------------------------------------------------+
+| os_storage_url          | Storage endpoint URL, if applicable                          |
++-------------------------+--------------------------------------------------------------+
+| os_project_domain_name  | Project domain name for authentication.                      |
++-------------------------+--------------------------------------------------------------+
+| os_user_domain_name     | User domain name for authentication.                         |
++-------------------------+--------------------------------------------------------------+
 
 Providing access credentials through environment variables
 ----------------------------------------------------------
@@ -260,7 +308,15 @@ OpenStack
 +------------------------+-----------+
 | OS_REGION_NAME         | ✔         |
 +------------------------+-----------+
-| OS_ZONE_NAME           |           |
+| OS_ZONE_NAME           | ✔         |
++------------------------+-----------+
+| OS_COMPUTE_ZONE_NAME   |           |
++------------------------+-----------+
+| OS_NETWORKING_ZONE_NAME|           |
++------------------------+-----------+
+| OS_SECURITY_ZONE_NAME  |           |
++------------------------+-----------+
+| OS_STORAGE_ZONE_NAME   |           |
 +------------------------+-----------+
 | NOVA_SERVICE_NAME      |           |
 +------------------------+-----------+
@@ -272,6 +328,10 @@ OpenStack
 +------------------------+-----------+
 | OS_STORAGE_URL         |           |
 +------------------------+-----------+
+| OS_PROJECT_DOMAIN_NAME |           |
++------------------------+-----------+
+| OS_USER_DOMAIN_NAME    |           |
++------------------------+-----------+
 
 Once the environment variables are set, you can create a connection as follows,
 replacing ``ProviderList.AWS`` with the desired provider (AZURE, GCP, or