]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/orchestrator: report external endpoints from 'orch ls'
authorSage Weil <sage@newdream.net>
Fri, 9 Apr 2021 22:47:52 +0000 (18:47 -0400)
committerSage Weil <sage@newdream.net>
Tue, 13 Apr 2021 20:52:42 +0000 (16:52 -0400)
Add a PORTS column and report the external/virtual IP (and port(s)) from
'orch ls' output.

Signed-off-by: Sage Weil <sage@newdream.net>
src/pybind/mgr/cephadm/module.py
src/pybind/mgr/cephadm/tests/test_cephadm.py
src/pybind/mgr/orchestrator/_interface.py
src/pybind/mgr/orchestrator/module.py
src/python-common/ceph/deployment/service_spec.py

index 7060dbcd87f5f6e70a90e95fbcf46649e0f347ad..56c3bac41f5087c8eda2e0a581707e4dfff8b3d0 100644 (file)
@@ -1577,6 +1577,8 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
                 events=self.events.get_for_service(spec.service_name()),
                 created=self.spec_store.spec_created[nm],
                 deleted=self.spec_store.spec_deleted.get(nm, None),
+                virtual_ip=spec.get_virtual_ip(),
+                ports=spec.get_port_start(),
             )
             if service_type == 'nfs':
                 spec = cast(NFSServiceSpec, spec)
index 2bf645de61964a42fba56d69257f5585e0bae2a0..f0896b9f96b607a5d242c12db448b9dfc85a5254 100644 (file)
@@ -148,7 +148,8 @@ class TestCephadm(object):
                             'service_id': 'r.z',
                             'service_name': 'rgw.r.z',
                             'service_type': 'rgw',
-                            'status': {'created': mock.ANY, 'running': 1, 'size': 1},
+                            'status': {'created': mock.ANY, 'running': 1, 'size': 1,
+                                       'ports': [80]},
                         }
                     ]
                     for o in out:
index 9d1808fda9390f6119ea59f60d489e541e6dbd79..9b2c1e1fa88d90aff24b6c2be924daa5b20723bd 100644 (file)
@@ -1023,7 +1023,9 @@ class ServiceDescription(object):
                  deleted: Optional[datetime.datetime] = None,
                  size: int = 0,
                  running: int = 0,
-                 events: Optional[List['OrchestratorEvent']] = None) -> None:
+                 events: Optional[List['OrchestratorEvent']] = None,
+                 virtual_ip: Optional[str] = None,
+                 ports: List[int] = []) -> None:
         # Not everyone runs in containers, but enough people do to
         # justify having the container_image_id (image hash) and container_image
         # (image name)
@@ -1053,12 +1055,20 @@ class ServiceDescription(object):
 
         self.events: List[OrchestratorEvent] = events or []
 
+        self.virtual_ip = virtual_ip
+        self.ports = ports
+
     def service_type(self) -> str:
         return self.spec.service_type
 
     def __repr__(self) -> str:
         return f"<ServiceDescription of {self.spec.one_line_str()}>"
 
+    def get_port_summary(self) -> str:
+        if not self.ports:
+            return ''
+        return f"{self.virtual_ip or '?'}:{','.join(map(str, self.ports or []))}"
+
     def to_json(self) -> OrderedDict:
         out = self.spec.to_json()
         status = {
@@ -1070,6 +1080,8 @@ class ServiceDescription(object):
             'running': self.running,
             'last_refresh': self.last_refresh,
             'created': self.created,
+            'virtual_ip': self.virtual_ip,
+            'ports': self.ports if self.ports else None,
         }
         for k in ['last_refresh', 'created']:
             if getattr(self, k):
index d4fb259ce4b76a410545c2d71ce3178e2e688651..cdf939d6be84faf21ffaa5b1a0c127eb39bbb1bb 100644 (file)
@@ -561,11 +561,14 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
         else:
             now = datetime_now()
             table = PrettyTable(
-                ['NAME', 'RUNNING', 'REFRESHED', 'AGE',
-                 'PLACEMENT',
-                 ],
+                [
+                    'NAME', 'PORTS',
+                    'RUNNING', 'REFRESHED', 'AGE',
+                    'PLACEMENT',
+                ],
                 border=False)
             table.align['NAME'] = 'l'
+            table.align['PORTS'] = 'l'
             table.align['RUNNING'] = 'r'
             table.align['REFRESHED'] = 'l'
             table.align['AGE'] = 'l'
@@ -586,6 +589,7 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
 
                 table.add_row((
                     s.spec.service_name(),
+                    s.get_port_summary(),
                     '%d/%d' % (s.running, s.size),
                     refreshed,
                     nice_delta(now, s.created),
index d7f10fe09da6b3e67f3be3d51b189cf7f30311be..75d99a0f61cba635dbe46407b4cc7e9f3d9b10eb 100644 (file)
@@ -581,6 +581,9 @@ class ServiceSpec(object):
         # point.
         return []
 
+    def get_virtual_ip(self) -> Optional[str]:
+        return None
+
     def to_json(self):
         # type: () -> OrderedDict[str, Any]
         ret: OrderedDict[str, Any] = OrderedDict()
@@ -901,6 +904,9 @@ class IngressSpec(ServiceSpec):
         return [cast(int, self.frontend_port),
                 cast(int, self.monitor_port)]
 
+    def get_virtual_ip(self) -> Optional[str]:
+        return self.virtual_ip
+
     def validate(self) -> None:
         super(IngressSpec, self).validate()