1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2#   not use this file except in compliance with the License. You may obtain
3#   a copy of the License at
4#
5#        http://www.apache.org/licenses/LICENSE-2.0
6#
7#   Unless required by applicable law or agreed to in writing, software
8#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10#   License for the specific language governing permissions and limitations
11#   under the License.
12#
13
14"""Metering Label Implementations"""
15
16import logging
17
18from osc_lib.cli import format_columns
19from osc_lib.command import command
20from osc_lib import exceptions
21from osc_lib import utils
22
23from openstackclient.i18n import _
24from openstackclient.identity import common as identity_common
25from openstackclient.network import sdk_utils
26
27LOG = logging.getLogger(__name__)
28
29
30_formatters = {
31    'location': format_columns.DictColumn,
32}
33
34
35def _get_columns(item):
36    column_map = {
37        'is_shared': 'shared',
38        'tenant_id': 'project_id',
39    }
40    return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
41
42
43def _get_attrs(client_manager, parsed_args):
44    attrs = {}
45
46    if parsed_args.description is not None:
47        attrs['description'] = parsed_args.description
48    if parsed_args.project is not None and 'project' in parsed_args:
49        identity_client = client_manager.identity
50        project_id = identity_common.find_project(
51            identity_client,
52            parsed_args.project,
53            parsed_args.project_domain,
54        ).id
55        attrs['tenant_id'] = project_id
56    if parsed_args.share:
57        attrs['shared'] = True
58    if parsed_args.no_share:
59        attrs['shared'] = False
60    if parsed_args.name is not None:
61        attrs['name'] = parsed_args.name
62
63    return attrs
64
65
66# TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the
67# OSC minimum requirements include SDK 1.0.
68class CreateMeter(command.ShowOne):
69    _description = _("Create network meter")
70
71    def get_parser(self, prog_name):
72        parser = super(CreateMeter, self).get_parser(prog_name)
73
74        parser.add_argument(
75            '--description',
76            metavar='<description>',
77            help=_("Create description for meter")
78        )
79        parser.add_argument(
80            '--project',
81            metavar='<project>',
82            help=_("Owner's project (name or ID)")
83        )
84
85        identity_common.add_project_domain_option_to_parser(parser)
86        share_group = parser.add_mutually_exclusive_group()
87        share_group.add_argument(
88            '--share',
89            action='store_true',
90            default=None,
91            help=_("Share meter between projects")
92        )
93        share_group.add_argument(
94            '--no-share',
95            action='store_true',
96            help=_("Do not share meter between projects")
97        )
98        parser.add_argument(
99            'name',
100            metavar='<name>',
101            help=_('Name of meter'),
102        )
103
104        return parser
105
106    def take_action(self, parsed_args):
107        client = self.app.client_manager.network
108        attrs = _get_attrs(self.app.client_manager, parsed_args)
109        obj = client.create_metering_label(**attrs)
110        display_columns, columns = _get_columns(obj)
111        data = utils.get_item_properties(obj, columns, formatters=_formatters)
112
113        return (display_columns, data)
114
115
116# TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the
117# OSC minimum requirements include SDK 1.0.
118class DeleteMeter(command.Command):
119    _description = _("Delete network meter")
120
121    def get_parser(self, prog_name):
122        parser = super(DeleteMeter, self).get_parser(prog_name)
123
124        parser.add_argument(
125            'meter',
126            metavar='<meter>',
127            nargs='+',
128            help=_('Meter to delete (name or ID)')
129        )
130        return parser
131
132    def take_action(self, parsed_args):
133        client = self.app.client_manager.network
134        result = 0
135
136        for meter in parsed_args.meter:
137            try:
138                obj = client.find_metering_label(meter, ignore_missing=False)
139                client.delete_metering_label(obj)
140            except Exception as e:
141                result += 1
142                LOG.error(_("Failed to delete meter with "
143                            "ID '%(meter)s': %(e)s"),
144                          {"meter": meter, "e": e})
145        if result > 0:
146            total = len(parsed_args.meter)
147            msg = (_("%(result)s of %(total)s meters failed "
148                     "to delete.") % {"result": result, "total": total})
149            raise exceptions.CommandError(msg)
150
151
152class ListMeter(command.Lister):
153    _description = _("List network meters")
154
155    def take_action(self, parsed_args):
156        client = self.app.client_manager.network
157
158        columns = (
159            'id',
160            'name',
161            'description',
162            'shared',
163        )
164        column_headers = (
165            'ID',
166            'Name',
167            'Description',
168            'Shared',
169        )
170
171        data = client.metering_labels()
172        return (column_headers,
173                (utils.get_item_properties(
174                    s, columns,
175                ) for s in data))
176
177
178class ShowMeter(command.ShowOne):
179    _description = _("Show network meter")
180
181    def get_parser(self, prog_name):
182        parser = super(ShowMeter, self).get_parser(prog_name)
183        parser.add_argument(
184            'meter',
185            metavar='<meter>',
186            help=_('Meter to display (name or ID)')
187        )
188        return parser
189
190    def take_action(self, parsed_args):
191        client = self.app.client_manager.network
192        obj = client.find_metering_label(parsed_args.meter,
193                                         ignore_missing=False)
194        display_columns, columns = _get_columns(obj)
195        data = utils.get_item_properties(obj, columns, formatters=_formatters)
196        return display_columns, data
197