]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm: allow for multiple vip configuration on ingress service
authorLuis Domingues <domingues.luis@protonmail.ch>
Mon, 8 Aug 2022 16:27:57 +0000 (18:27 +0200)
committerAdam King <adking@redhat.com>
Tue, 6 Sep 2022 14:56:17 +0000 (10:56 -0400)
Signed-off-by: Luis Domingues <domingues.luis@protonmail.ch>
(cherry picked from commit 0193a6f73659f7aa4ac1d000cf11c6544ad6ab6d)

src/pybind/mgr/cephadm/services/ingress.py
src/pybind/mgr/cephadm/templates/services/ingress/keepalived.conf.j2
src/python-common/ceph/deployment/service_spec.py

index 9460af1dd7a272fef5e44143481b52a1b4f21149..bcd63e91a101cef359d3ce9f503f9361181486c8 100644 (file)
@@ -196,7 +196,10 @@ class IngressService(CephService):
         hosts = sorted(list(set([host] + [str(d.hostname) for d in daemons])))
 
         # interface
-        bare_ip = str(spec.virtual_ip).split('/')[0]
+        if spec.virtual_ip:
+            bare_ip = str(spec.virtual_ip).split('/')[0]
+        elif spec.virtual_ips_list:
+            bare_ip = str(spec.virtual_ips_list[0]).split('/')[0]
         interface = None
         for subnet, ifaces in self.mgr.cache.networks.get(host, {}).items():
             if ifaces and ipaddress.ip_address(bare_ip) in ipaddress.ip_network(subnet):
@@ -230,10 +233,33 @@ class IngressService(CephService):
                     script = f'/usr/bin/curl {build_url(scheme="http", host=d.ip or "localhost", port=port)}/health'
         assert script
 
-        # set state. first host in placement is master all others backups
-        state = 'BACKUP'
-        if hosts[0] == host:
-            state = 'MASTER'
+        states = []
+        priorities = []
+        virtual_ips = []
+
+        # Set state and priority. Have one master for each VIP. Or at least the first one as master if only one VIP.
+        if spec.virtual_ip:
+            virtual_ips.append(spec.virtual_ip)
+            if hosts[0] == host:
+                states.append('MASTER')
+                priorities.append(100)
+            else:
+                states.append('BACKUP')
+                priorities.append(90)
+
+        elif spec.virtual_ips_list:
+            virtual_ips = spec.virtual_ips_list
+            if len(virtual_ips) > len(hosts):
+                raise OrchestratorError(
+                    "Number of virtual IPs for ingress is greater than number of available hosts"
+                )
+            for x in range(len(virtual_ips)):
+                if hosts[x] == host:
+                    states.append('MASTER')
+                    priorities.append(100)
+                else:
+                    states.append('BACKUP')
+                    priorities.append(90)
 
         # remove host, daemon is being deployed on from hosts list for
         # other_ips in conf file and converter to ips
@@ -248,7 +274,9 @@ class IngressService(CephService):
                 'script': script,
                 'password': password,
                 'interface': interface,
-                'state': state,
+                'virtual_ips': virtual_ips,
+                'states': states,
+                'priorities': priorities,
                 'other_ips': other_ips,
                 'host_ip': resolve_ip(self.mgr.inventory.get_addr(host)),
             }
index 4caeebf51f9e0cc2727d30232cefc90fc0733e49..f560c9756654d0d51a025dc37d668ee7575023da 100644 (file)
@@ -7,11 +7,12 @@ vrrp_script check_backend {
     fall 2
 }
 
-vrrp_instance VI_0 {
-  state {{ state }}
-  priority 100
+{% for x in range(virtual_ips|length) %}
+vrrp_instance VI_{{ x }} {
+  state {{ states[x] }}
+  priority {{ priorities[x] }}
   interface {{ interface }}
-  virtual_router_id 51
+  virtual_router_id {{ 50 + x }}
   advert_int 1
   authentication {
       auth_type PASS
@@ -24,9 +25,10 @@ vrrp_instance VI_0 {
     {% endfor %}
   }
   virtual_ipaddress {
-    {{ spec.virtual_ip }} dev {{ interface }}
+    {{ virtual_ips[x] }} dev {{ interface }}
   }
   track_script {
       check_backend
   }
 }
+{% endfor %}
index 40e082dabf5929b57baf055ebfc0f3bf9851dace..e105ea8ebdff4aab813f0f3687563fb85f0197af 100644 (file)
@@ -935,12 +935,14 @@ class IngressSpec(ServiceSpec):
                  enable_stats: Optional[bool] = None,
                  keepalived_password: Optional[str] = None,
                  virtual_ip: Optional[str] = None,
+                 virtual_ips_list: Optional[List[str]] = None,
                  virtual_interface_networks: Optional[List[str]] = [],
                  unmanaged: bool = False,
                  ssl: bool = False,
                  extra_container_args: Optional[List[str]] = None,
                  ):
         assert service_type == 'ingress'
+
         super(IngressSpec, self).__init__(
             'ingress', service_id=service_id,
             placement=placement, config=config,
@@ -959,6 +961,7 @@ class IngressSpec(ServiceSpec):
         self.monitor_password = monitor_password
         self.keepalived_password = keepalived_password
         self.virtual_ip = virtual_ip
+        self.virtual_ips_list = virtual_ips_list
         self.virtual_interface_networks = virtual_interface_networks or []
         self.unmanaged = unmanaged
         self.ssl = ssl
@@ -982,9 +985,12 @@ class IngressSpec(ServiceSpec):
         if not self.monitor_port:
             raise SpecValidationError(
                 'Cannot add ingress: No monitor_port specified')
-        if not self.virtual_ip:
+        if not self.virtual_ip and not self.virtual_ips_list:
             raise SpecValidationError(
                 'Cannot add ingress: No virtual_ip provided')
+        if self.virtual_ip is not None and self.virtual_ips_list is not None:
+            raise SpecValidationError(
+                'Cannot add ingress: Single and multiple virtual IPs specified')
 
 
 yaml.add_representer(IngressSpec, ServiceSpec.yaml_representer)