diff --git a/doc/source/command-objects/server-group.rst b/doc/source/command-objects/server-group.rst
index af0090c7f9..acf9be345a 100644
--- a/doc/source/command-objects/server-group.rst
+++ b/doc/source/command-objects/server-group.rst
@@ -43,3 +43,23 @@ Delete an existing server group
 
     Server group(s) to delete (name or ID)
     (repeat to delete multiple server groups)
+
+server group list
+-----------------
+
+List all server groups
+
+.. program:: server group list
+.. code-block:: bash
+
+    os server group list
+        [--all-projects]
+        [--long]
+
+.. option:: --all-projects
+
+    Display information from all projects (admin only)
+
+.. option:: --long
+
+    List additional fields in output
diff --git a/openstackclient/compute/v2/server_group.py b/openstackclient/compute/v2/server_group.py
index 02de011efe..56d7e27a80 100644
--- a/openstackclient/compute/v2/server_group.py
+++ b/openstackclient/compute/v2/server_group.py
@@ -99,3 +99,60 @@ class DeleteServerGroup(command.Command):
             total = len(parsed_args.server_group)
             msg = "%s of %s server groups failed to delete." % (result, total)
             raise exceptions.CommandError(msg)
+
+
+class ListServerGroup(command.Lister):
+    """List all server groups."""
+
+    def get_parser(self, prog_name):
+        parser = super(ListServerGroup, self).get_parser(prog_name)
+        parser.add_argument(
+            '--all-projects',
+            action='store_true',
+            default=False,
+            help='Display information from all projects (admin only)',
+        )
+        parser.add_argument(
+            '--long',
+            action='store_true',
+            default=False,
+            help='List additional fields in output',
+        )
+        return parser
+
+    def take_action(self, parsed_args):
+        compute_client = self.app.client_manager.compute
+        data = compute_client.server_groups.list(parsed_args.all_projects)
+
+        if parsed_args.long:
+            column_headers = (
+                'ID',
+                'Name',
+                'Policies',
+                'Members',
+                'Project Id',
+                'User Id',
+            )
+            columns = (
+                'ID',
+                'Name',
+                'Policies',
+                'Members',
+                'Project Id',
+                'User Id',
+            )
+        else:
+            column_headers = columns = (
+                'ID',
+                'Name',
+                'Policies',
+            )
+
+        return (column_headers,
+                (utils.get_item_properties(
+                    s, columns,
+                    formatters={
+                        'Policies': utils.format_list,
+                        'Members': utils.format_list,
+                    }
+                ) for s in data))
diff --git a/openstackclient/tests/compute/v2/test_server_group.py b/openstackclient/tests/compute/v2/test_server_group.py
index 3bd1177b89..a18c60148b 100644
--- a/openstackclient/tests/compute/v2/test_server_group.py
+++ b/openstackclient/tests/compute/v2/test_server_group.py
@@ -190,3 +190,71 @@ class TestServerGroupDelete(TestServerGroup):
             self.server_groups_mock.delete.assert_called_once_with(
                 self.fake_server_group.id
             )
+
+
+class TestServerGroupList(TestServerGroup):
+
+    list_columns = (
+        'ID',
+        'Name',
+        'Policies',
+    )
+
+    list_columns_long = (
+        'ID',
+        'Name',
+        'Policies',
+        'Members',
+        'Project Id',
+        'User Id',
+    )
+
+    list_data = ((
+        TestServerGroup.fake_server_group.id,
+        TestServerGroup.fake_server_group.name,
+        utils.format_list(TestServerGroup.fake_server_group.policies),
+    ),)
+
+    list_data_long = ((
+        TestServerGroup.fake_server_group.id,
+        TestServerGroup.fake_server_group.name,
+        utils.format_list(TestServerGroup.fake_server_group.policies),
+        utils.format_list(TestServerGroup.fake_server_group.members),
+        TestServerGroup.fake_server_group.project_id,
+        TestServerGroup.fake_server_group.user_id,
+    ),)
+
+    def setUp(self):
+        super(TestServerGroupList, self).setUp()
+
+        self.server_groups_mock.list.return_value = [self.fake_server_group]
+        self.cmd = server_group.ListServerGroup(self.app, None)
+
+    def test_server_group_list(self):
+        arglist = []
+        verifylist = [
+            ('all_projects', False),
+            ('long', False),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        columns, data = self.cmd.take_action(parsed_args)
+        self.server_groups_mock.list.assert_called_once_with(False)
+
+        self.assertEqual(self.list_columns, columns)
+        self.assertEqual(self.list_data, tuple(data))
+
+    def test_server_group_list_with_all_projects_and_long(self):
+        arglist = [
+            '--all-projects',
+            '--long',
+        ]
+        verifylist = [
+            ('all_projects', True),
+            ('long', True),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        columns, data = self.cmd.take_action(parsed_args)
+        self.server_groups_mock.list.assert_called_once_with(True)
+
+        self.assertEqual(self.list_columns_long, columns)
+        self.assertEqual(self.list_data_long, tuple(data))
diff --git a/setup.cfg b/setup.cfg
index dedd607ea8..c6e7619c2d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -133,6 +133,7 @@ openstack.compute.v2 =
 
     server_group_create = openstackclient.compute.v2.server_group:CreateServerGroup
     server_group_delete = openstackclient.compute.v2.server_group:DeleteServerGroup
+    server_group_list = openstackclient.compute.v2.server_group:ListServerGroup
 
     usage_list = openstackclient.compute.v2.usage:ListUsage
     usage_show = openstackclient.compute.v2.usage:ShowUsage