~ubuntu-branches/ubuntu/raring/nova/raring-proposed

« back to all changes in this revision

Viewing changes to bin/nova-manage

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 09:04:58 UTC
  • mfrom: (1.1.66)
  • Revision ID: package-import@ubuntu.com-20121123090458-91565o7aev1i1h71
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/control: Ensure novaclient is upgraded with nova,
  require python-keystoneclient >= 1:2.9.0. (LP: #1073289)
* debian/patches/{ubuntu/*, rbd-security.patch}: Dropped, applied
  upstream.
* debian/control: Add python-testtools to Build-Depends.

[ Chuck Short ]
* New upstream version.
* Refreshed debian/patches/avoid_setuptools_git_dependency.patch.
* debian/rules: FTBFS if missing binaries.
* debian/nova-scheudler.install: Add missing rabbit-queues and
  nova-rpc-zmq-receiver.
* Remove nova-volume since it doesnt exist anymore, transition to cinder-*.
* debian/rules: install apport hook in the right place.
* debian/patches/ubuntu-show-tests.patch: Display test failures.
* debian/control: Add depends on genisoimage
* debian/control: Suggest guestmount.
* debian/control: Suggest websockify. (LP: #1076442)
* debian/nova.conf: Disable nova-volume service.
* debian/control: Depend on xen-system-* rather than the hypervisor.
* debian/control, debian/mans/nova-conductor.8, debian/nova-conductor.init,
  debian/nova-conductor.install, debian/nova-conductor.logrotate
  debian/nova-conductor.manpages, debian/nova-conductor.postrm
  debian/nova-conductor.upstart.in: Add nova-conductor service.
* debian/control: Add python-fixtures as a build deps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
  CLI interface for nova management.
55
55
"""
56
56
 
57
 
import ast
58
 
import errno
59
57
import gettext
60
 
import math
61
58
import netaddr
62
59
import optparse
63
60
import os
74
71
gettext.install('nova', unicode=1)
75
72
 
76
73
from nova.api.ec2 import ec2utils
77
 
from nova.compat import flagfile
78
74
from nova.compute import instance_types
79
75
from nova.compute import rpcapi as compute_rpcapi
 
76
from nova import config
80
77
from nova import context
81
78
from nova import db
82
79
from nova.db import migration
83
80
from nova import exception
84
 
from nova import flags
85
81
from nova.openstack.common import cfg
86
82
from nova.openstack.common import importutils
87
83
from nova.openstack.common import log as logging
92
88
from nova import utils
93
89
from nova import version
94
90
 
95
 
FLAGS = flags.FLAGS
96
 
flags.DECLARE('flat_network_bridge', 'nova.network.manager')
97
 
flags.DECLARE('num_networks', 'nova.network.manager')
98
 
flags.DECLARE('multi_host', 'nova.network.manager')
99
 
flags.DECLARE('network_size', 'nova.network.manager')
100
 
flags.DECLARE('vlan_start', 'nova.network.manager')
101
 
flags.DECLARE('vpn_start', 'nova.network.manager')
102
 
flags.DECLARE('default_floating_pool', 'nova.network.manager')
103
 
flags.DECLARE('public_interface', 'nova.network.linux_net')
 
91
CONF = cfg.CONF
 
92
CONF.import_opt('network_manager', 'nova.config')
 
93
CONF.import_opt('service_down_time', 'nova.config')
 
94
CONF.import_opt('flat_network_bridge', 'nova.network.manager')
 
95
CONF.import_opt('num_networks', 'nova.network.manager')
 
96
CONF.import_opt('multi_host', 'nova.network.manager')
 
97
CONF.import_opt('network_size', 'nova.network.manager')
 
98
CONF.import_opt('vlan_start', 'nova.network.manager')
 
99
CONF.import_opt('vpn_start', 'nova.network.manager')
 
100
CONF.import_opt('default_floating_pool', 'nova.network.manager')
 
101
CONF.import_opt('public_interface', 'nova.network.linux_net')
104
102
 
105
103
QUOTAS = quota.QUOTAS
106
104
 
225
223
    def quota(self, project_id, key=None, value=None):
226
224
        """Set or display quotas for project"""
227
225
        ctxt = context.get_admin_context()
228
 
        if key:
 
226
        project_quota = QUOTAS.get_project_quotas(ctxt, project_id)
 
227
        if key and key in project_quota:
229
228
            if value.lower() == 'unlimited':
230
229
                value = -1
231
230
            try:
232
231
                db.quota_update(ctxt, project_id, key, value)
233
232
            except exception.ProjectQuotaNotFound:
234
233
                db.quota_create(ctxt, project_id, key, value)
 
234
        else:
 
235
            print _('%(key)s is not a valid quota key. Valid options are: '
 
236
                    '%(options)s.') % {'key': key,
 
237
                                       'options': ', '.join(project_quota)}
 
238
            sys.exit(2)
235
239
        project_quota = QUOTAS.get_project_quotas(ctxt, project_id)
236
240
        for key, value in project_quota.iteritems():
237
241
            if value['limit'] < 0 or value['limit'] is None:
268
272
            else:
269
273
                fixed_ips = db.fixed_ip_get_all_by_instance_host(ctxt, host)
270
274
        except exception.NotFound as ex:
271
 
            print "error: %s" % ex
 
275
            print _("error: %s") % ex
272
276
            sys.exit(2)
273
277
 
274
278
        instances = db.instance_get_all(context.get_admin_context())
342
346
            db.fixed_ip_update(ctxt, fixed_ip['address'],
343
347
                                {'reserved': reserved})
344
348
        except exception.NotFound as ex:
345
 
            print "error: %s" % ex
 
349
            print _("error: %s") % ex
346
350
            sys.exit(2)
347
351
 
348
352
 
376
380
        """Creates floating ips for zone by range"""
377
381
        admin_context = context.get_admin_context()
378
382
        if not pool:
379
 
            pool = FLAGS.default_floating_pool
 
383
            pool = CONF.default_floating_pool
380
384
        if not interface:
381
 
            interface = FLAGS.public_interface
 
385
            interface = CONF.public_interface
382
386
 
383
387
        ips = ({'address': str(address), 'pool': pool, 'interface': interface}
384
388
               for address in self.address_to_hosts(ip_range))
472
476
                       if v and k != "self"))
473
477
        if multi_host is not None:
474
478
            kwargs['multi_host'] = multi_host == 'T'
475
 
        net_manager = importutils.import_object(FLAGS.network_manager)
 
479
        net_manager = importutils.import_object(CONF.network_manager)
476
480
        net_manager.create_networks(context.get_admin_context(), **kwargs)
477
481
 
478
482
    def list(self):
516
520
        if fixed_range is None and uuid is None:
517
521
            raise Exception("Please specify either fixed_range or uuid")
518
522
 
519
 
        net_manager = importutils.import_object(FLAGS.network_manager)
520
 
        if "QuantumManager" in FLAGS.network_manager:
 
523
        net_manager = importutils.import_object(CONF.network_manager)
 
524
        if "QuantumManager" in CONF.network_manager:
521
525
            if uuid is None:
522
526
                raise Exception("UUID is required to delete Quantum Networks")
523
527
            if fixed_range:
631
635
                    _('Updated_At'))
632
636
        for svc in services:
633
637
            delta = now - (svc['updated_at'] or svc['created_at'])
634
 
            alive = abs(utils.total_seconds(delta)) <= FLAGS.service_down_time
 
638
            alive = abs(utils.total_seconds(delta)) <= CONF.service_down_time
635
639
            art = (alive and ":-)") or "XXX"
636
640
            active = 'enabled'
637
641
            if svc['disabled']:
648
652
        ctxt = context.get_admin_context()
649
653
        svc = db.service_get_by_args(ctxt, host, service)
650
654
        if not svc:
651
 
            print "Unable to find service"
 
655
            print _("Unable to find service")
652
656
            return
653
657
        db.service_update(ctxt, svc['id'], {'disabled': False})
654
658
 
660
664
        ctxt = context.get_admin_context()
661
665
        svc = db.service_get_by_args(ctxt, host, service)
662
666
        if not svc:
663
 
            print "Unable to find service"
 
667
            print _("Unable to find service")
664
668
            return
665
669
        db.service_update(ctxt, svc['id'], {'disabled': True})
666
670
 
775
779
        self.list()
776
780
 
777
781
 
778
 
class VolumeCommands(object):
779
 
    """Methods for dealing with a cloud in an odd state"""
780
 
 
781
 
    @args('--volume', dest='volume_id', metavar='<volume id>',
782
 
            help='Volume ID')
783
 
    def delete(self, volume_id):
784
 
        """WARNING: This method is deprecated and will be removed.
785
 
        Delete a volume, bypassing the check that it
786
 
        must be available."""
787
 
 
788
 
        print(_("\"nova-manage volume delete\" is deprecated; use"
789
 
                " the os-reset_status os-admin-actions extension instead."))
790
 
        if 'cinder' in FLAGS.volume_api_class:
791
 
            print(_("\"nova-manage volume delete\" only valid "
792
 
                    "when using nova-volume service"))
793
 
            sys.exit(1)
794
 
 
795
 
        ctxt = context.get_admin_context()
796
 
        volume = db.volume_get(ctxt, param2id(volume_id))
797
 
        host = volume['host']
798
 
 
799
 
        if not host:
800
 
            print "Volume not yet assigned to host."
801
 
            print "Deleting volume from database and skipping rpc."
802
 
            db.volume_destroy(ctxt, volume_id)
803
 
            return
804
 
 
805
 
        if volume['status'] == 'in-use':
806
 
            print "Volume is in-use."
807
 
            print "Detach volume from instance and then try again."
808
 
            return
809
 
 
810
 
        rpc.cast(ctxt,
811
 
                 rpc.queue_get_for(ctxt, FLAGS.volume_topic, host),
812
 
                 {"method": "delete_volume",
813
 
                  "args": {"volume_id": volume['id']}})
814
 
 
815
 
    @args('--volume', dest='volume_id', metavar='<volume id>',
816
 
            help='Volume ID')
817
 
    def reattach(self, volume_id):
818
 
        """Re-attach a volume that has previously been attached
819
 
        to an instance.  Typically called after a compute host
820
 
        has been rebooted."""
821
 
 
822
 
        if 'cinder' in FLAGS.volume_api_class:
823
 
            print(_("\"nova-manage volume reattach\" only valid "
824
 
                    "when using nova-volume service"))
825
 
            sys.exit(1)
826
 
 
827
 
        ctxt = context.get_admin_context()
828
 
        volume = db.volume_get(ctxt, param2id(volume_id))
829
 
 
830
 
        if not volume['instance_id']:
831
 
            print "volume is not attached to an instance"
832
 
            return
833
 
        instance = db.instance_get(ctxt, volume['instance_id'])
834
 
        rpcapi = compute_rpcapi.ComputeAPI()
835
 
        rpcapi.attach_volume(ctxt, instance, volume['id'],
836
 
                             volume['mountpoint'])
837
 
 
838
 
 
839
782
class InstanceTypeCommands(object):
840
783
    """Class for managing instance types / flavors."""
841
784
 
864
807
            help='rxtx_factor')
865
808
    @args('--is_public', dest="is_public", metavar='<is_public>',
866
809
            help='Make flavor accessible to the public')
867
 
    def create(self, name, memory, vcpus, root_gb, ephemeral_gb, flavorid=None,
868
 
               swap=0, rxtx_factor=1, is_public=True):
 
810
    def create(self, name, memory, vcpus, root_gb, ephemeral_gb=0,
 
811
               flavorid=None, swap=0, rxtx_factor=1, is_public=True):
869
812
        """Creates instance types / flavors"""
870
813
        try:
871
814
            instance_types.create(name, memory, vcpus, root_gb,
872
815
                                  ephemeral_gb, flavorid, swap, rxtx_factor,
873
816
                                  is_public)
874
817
        except exception.InvalidInput, e:
875
 
            print "Must supply valid parameters to create instance_type"
 
818
            print _("Must supply valid parameters to create instance_type")
876
819
            print e
877
820
            sys.exit(1)
878
821
        except exception.InstanceTypeExists:
879
 
            print "Instance Type exists."
880
 
            print "Please ensure instance_type name and flavorid are unique."
881
 
            print "Currently defined instance_type names and flavorids:"
 
822
            print _("Instance Type exists.")
 
823
            print _("Please ensure instance_type name and flavorid are "
 
824
                    "unique.")
 
825
            print _("Currently defined instance_type names and flavorids:")
882
826
            print
883
827
            self.list()
884
828
            sys.exit(2)
885
829
        except Exception:
886
 
            print "Unknown error"
 
830
            print _("Unknown error")
887
831
            sys.exit(3)
888
832
        else:
889
 
            print "%s created" % name
 
833
            print _("%s created") % name
890
834
 
891
835
    @args('--name', dest='name', metavar='<name>',
892
836
            help='Name of instance type/flavor')
895
839
        try:
896
840
            instance_types.destroy(name)
897
841
        except exception.InstanceTypeNotFound:
898
 
            print "Valid instance type name is required"
 
842
            print _("Valid instance type name is required")
899
843
            sys.exit(1)
900
844
        except exception.DBError, e:
901
 
            print "DB Error: %s" % e
 
845
            print _("DB Error: %s") % e
902
846
            sys.exit(2)
903
847
        except Exception:
904
848
            sys.exit(3)
905
849
        else:
906
 
            print "%s deleted" % name
 
850
            print _("%s deleted") % name
907
851
 
908
852
    @args('--name', dest='name', metavar='<name>',
909
853
            help='Name of instance type/flavor')
944
888
                            inst_type["flavorid"],
945
889
                            ext_spec)
946
890
            print _("Key %(key)s set to %(value)s on instance"
947
 
                            " type %(name)s") % locals()
 
891
                    " type %(name)s") % locals()
948
892
        except exception.DBError, e:
949
893
            _db_error(e)
950
894
 
972
916
            _db_error(e)
973
917
 
974
918
 
975
 
class StorageManagerCommands(object):
976
 
    """Class for mangaging Storage Backends and Flavors"""
977
 
 
978
 
    def flavor_list(self, flavor=None):
979
 
        ctxt = context.get_admin_context()
980
 
 
981
 
        try:
982
 
            if flavor is None:
983
 
                flavors = db.sm_flavor_get_all(ctxt)
984
 
            else:
985
 
                flavors = db.sm_flavor_get(ctxt, flavor)
986
 
        except exception.NotFound as ex:
987
 
            print "error: %s" % ex
988
 
            sys.exit(2)
989
 
 
990
 
        print "%-18s\t%-20s\t%s" % (_('id'),
991
 
                                    _('Label'),
992
 
                                    _('Description'))
993
 
 
994
 
        for flav in flavors:
995
 
            print "%-18s\t%-20s\t%s" % (
996
 
                    flav['id'],
997
 
                    flav['label'],
998
 
                    flav['description'])
999
 
 
1000
 
    def flavor_create(self, label, desc):
1001
 
        # TODO(renukaapte) flavor name must be unique
1002
 
        try:
1003
 
            db.sm_flavor_create(context.get_admin_context(),
1004
 
                                dict(label=label,
1005
 
                                     description=desc))
1006
 
        except exception.DBError, e:
1007
 
            _db_error(e)
1008
 
 
1009
 
    def flavor_delete(self, label):
1010
 
        try:
1011
 
            db.sm_flavor_delete(context.get_admin_context(), label)
1012
 
 
1013
 
        except exception.DBError, e:
1014
 
            _db_error(e)
1015
 
 
1016
 
    def _splitfun(self, item):
1017
 
        i = item.split("=")
1018
 
        return i[0:2]
1019
 
 
1020
 
    def backend_list(self, backend_conf_id=None):
1021
 
        ctxt = context.get_admin_context()
1022
 
 
1023
 
        try:
1024
 
            if backend_conf_id is None:
1025
 
                backends = db.sm_backend_conf_get_all(ctxt)
1026
 
            else:
1027
 
                backends = db.sm_backend_conf_get(ctxt, backend_conf_id)
1028
 
 
1029
 
        except exception.NotFound as ex:
1030
 
            print "error: %s" % ex
1031
 
            sys.exit(2)
1032
 
 
1033
 
        print "%-5s\t%-10s\t%-40s\t%-10s\t%s" % (_('id'),
1034
 
                                                      _('Flavor id'),
1035
 
                                                      _('SR UUID'),
1036
 
                                                      _('SR Type'),
1037
 
                                                      _('Config Parameters'),)
1038
 
 
1039
 
        for b in backends:
1040
 
            print "%-5s\t%-10s\t%-40s\t%-10s\t%s" % (b['id'],
1041
 
                                                     b['flavor_id'],
1042
 
                                                     b['sr_uuid'],
1043
 
                                                     b['sr_type'],
1044
 
                                                     b['config_params'],)
1045
 
 
1046
 
    def backend_add(self, flavor_label, sr_type, *args):
1047
 
        # TODO(renukaapte) Add backend_introduce.
1048
 
        ctxt = context.get_admin_context()
1049
 
        params = dict(map(self._splitfun, args))
1050
 
 
1051
 
        if 'sr_uuid' in params:
1052
 
            try:
1053
 
                backend = db.sm_backend_conf_get_by_sr(ctxt,
1054
 
                                                       params['sr_uuid'])
1055
 
            except exception.DBError, e:
1056
 
                _db_error(e)
1057
 
 
1058
 
            if backend:
1059
 
                print 'Backend config found. Would you like to recreate this?'
1060
 
                print '(WARNING:Recreating will destroy all VDIs on backend!!)'
1061
 
                c = raw_input('Proceed? (y/n) ')
1062
 
                if c == 'y' or c == 'Y':
1063
 
                    try:
1064
 
                        db.sm_backend_conf_update(ctxt, backend['id'],
1065
 
                                                  dict(created=False))
1066
 
                    except exception.DBError, e:
1067
 
                        _db_error(e)
1068
 
                return
1069
 
 
1070
 
            else:
1071
 
                print 'Backend config not found. Would you like to create it?'
1072
 
                print '(WARNING: Creating will destroy all data on backend!!!)'
1073
 
                c = raw_input('Proceed? (y/n) ')
1074
 
                if c != 'y' and c != 'Y':
1075
 
                    return
1076
 
 
1077
 
        print '(WARNING: Creating will destroy all data on backend!!!)'
1078
 
        c = raw_input('Proceed? (y/n) ')
1079
 
        if c == 'y' or c == 'Y':
1080
 
            if flavor_label is None:
1081
 
                print "error: backend needs to be associated with flavor"
1082
 
                sys.exit(2)
1083
 
 
1084
 
            try:
1085
 
                flavors = db.sm_flavor_get_by_label(ctxt, flavor_label)
1086
 
            except exception.NotFound as ex:
1087
 
                print "error: %s" % ex
1088
 
                sys.exit(2)
1089
 
 
1090
 
            config_params = "".join(['%s=%s ' %
1091
 
                                   (key, params[key]) for key in params])
1092
 
 
1093
 
            try:
1094
 
                db.sm_backend_conf_create(ctxt,
1095
 
                                          dict(flavor_id=flavors['id'],
1096
 
                                               sr_uuid=None,
1097
 
                                               sr_type=sr_type,
1098
 
                                               config_params=config_params))
1099
 
            except exception.DBError, e:
1100
 
                _db_error(e)
1101
 
 
1102
 
    def backend_remove(self, backend_conf_id):
1103
 
        try:
1104
 
            db.sm_backend_conf_delete(context.get_admin_context(),
1105
 
                                      backend_conf_id)
1106
 
 
1107
 
        except exception.DBError, e:
1108
 
            _db_error(e)
1109
 
 
1110
 
 
1111
919
class AgentBuildCommands(object):
1112
920
    """Class for managing agent builds."""
1113
921
 
1147
955
            if hypervisor and key != hypervisor:
1148
956
                continue
1149
957
 
1150
 
            print "Hypervisor: %s" % key
 
958
            print _('Hypervisor: %s') % key
1151
959
            print fmt % ('-' * 10, '-' * 8, '-' * 12, '-' * 32)
1152
960
            for agent_build in buildlist:
1153
961
                print fmt % (agent_build.os, agent_build.architecture,
1168
976
                               'md5hash': md5hash})
1169
977
 
1170
978
 
1171
 
class ConfigCommands(object):
1172
 
    """Class for exposing the flags defined by flag_file(s)."""
1173
 
 
1174
 
    def __init__(self):
1175
 
        pass
1176
 
 
1177
 
    def list(self):
1178
 
        for key, value in FLAGS.iteritems():
1179
 
            if value is not None:
1180
 
                print '%s = %s' % (key, value)
1181
 
 
1182
 
    @args('--infile', dest='infile', metavar='<path>',
1183
 
          help='old-style flagfile to convert to config')
1184
 
    @args('--outfile', dest='outfile', metavar='<path>',
1185
 
          help='path for output file. Writes config'
1186
 
               'to stdout if not specified.')
1187
 
    def convert(self, infile, outfile=None):
1188
 
        """Converts a flagfile and prints results to stdout."""
1189
 
        arg = '--flagfile=%s' % infile
1190
 
        with flagfile.handle_flagfiles_managed([arg]) as newargs:
1191
 
            with open(newargs[0].split('=')[1]) as configfile:
1192
 
                config = configfile.read()
1193
 
            if outfile:
1194
 
                with open(outfile, 'w') as configfile:
1195
 
                    configfile.write(config)
1196
 
            else:
1197
 
                print config,
1198
 
 
1199
 
 
1200
979
class GetLogCommands(object):
1201
980
    """Get logging information"""
1202
981
 
1203
982
    def errors(self):
1204
983
        """Get all of the errors from the log files"""
1205
984
        error_found = 0
1206
 
        if FLAGS.logdir:
1207
 
            logs = [x for x in os.listdir(FLAGS.logdir) if x.endswith('.log')]
 
985
        if CONF.logdir:
 
986
            logs = [x for x in os.listdir(CONF.logdir) if x.endswith('.log')]
1208
987
            for file in logs:
1209
 
                log_file = os.path.join(FLAGS.logdir, file)
 
988
                log_file = os.path.join(CONF.logdir, file)
1210
989
                lines = [line.strip() for line in open(log_file, "r")]
1211
990
                lines.reverse()
1212
991
                print_name = 0
1216
995
                        if print_name == 0:
1217
996
                            print log_file + ":-"
1218
997
                            print_name = 1
1219
 
                        print "Line %d : %s" % (len(lines) - index, line)
 
998
                        linenum = len(lines) - index
 
999
                        print _('Line %(linenum)d : %(line)s') % locals()
1220
1000
        if error_found == 0:
1221
 
            print "No errors in logfiles!"
 
1001
            print _('No errors in logfiles!')
1222
1002
 
1223
1003
    def syslog(self, num_entries=10):
1224
1004
        """Get <num_entries> of the nova syslog events"""
1230
1010
        elif os.path.exists('/var/log/messages'):
1231
1011
            log_file = '/var/log/messages'
1232
1012
        else:
1233
 
            print "Unable to find system log file!"
 
1013
            print _('Unable to find system log file!')
1234
1014
            sys.exit(1)
1235
1015
        lines = [line.strip() for line in open(log_file, "r")]
1236
1016
        lines.reverse()
1237
 
        print "Last %s nova syslog entries:-" % (entries)
 
1017
        print _('Last %s nova syslog entries:-') % (entries)
1238
1018
        for line in lines:
1239
1019
            if line.find("nova") > 0:
1240
1020
                count += 1
1243
1023
                break
1244
1024
 
1245
1025
        if count == 0:
1246
 
            print "No nova entries in syslog!"
 
1026
            print _('No nova entries in syslog!')
1247
1027
 
1248
1028
 
1249
1029
CATEGORIES = [
1250
1030
    ('account', AccountCommands),
1251
1031
    ('agent', AgentBuildCommands),
1252
 
    ('config', ConfigCommands),
1253
1032
    ('db', DbCommands),
1254
1033
    ('fixed', FixedIpCommands),
1255
1034
    ('flavor', InstanceTypeCommands),
1261
1040
    ('project', ProjectCommands),
1262
1041
    ('service', ServiceCommands),
1263
1042
    ('shell', ShellCommands),
1264
 
    ('sm', StorageManagerCommands),
1265
1043
    ('version', VersionCommands),
1266
1044
    ('vm', VmCommands),
1267
 
    ('volume', VolumeCommands),
1268
1045
    ('vpn', VpnCommands),
1269
1046
]
1270
1047
 
1278
1055
        if k.lower().find(name.lower()) == 0:
1279
1056
            result.append((k, v))
1280
1057
    if len(result) == 0:
1281
 
        print "%s does not match any options:" % name
 
1058
        print _('%s does not match any options:') % name
1282
1059
        for k, _v in key_value_tuples:
1283
1060
            print "\t%s" % k
1284
1061
        sys.exit(2)
1285
1062
    if len(result) > 1:
1286
 
        print "%s matched multiple options:" % name
 
1063
        print _('%s matched multiple options:') % name
1287
1064
        for k, _v in result:
1288
1065
            print "\t%s" % k
1289
1066
        sys.exit(2)
1304
1081
    """Parse options and call the appropriate class/method."""
1305
1082
 
1306
1083
    try:
1307
 
        argv = flags.parse_args(sys.argv)
 
1084
        argv = config.parse_args(sys.argv)
1308
1085
        logging.setup("nova")
1309
1086
    except cfg.ConfigFilesNotFoundError:
1310
 
        cfgfile = FLAGS.config_file[-1] if FLAGS.config_file else None
 
1087
        cfgfile = CONF.config_file[-1] if CONF.config_file else None
1311
1088
        if cfgfile and not os.access(cfgfile, os.R_OK):
1312
1089
            st = os.stat(cfgfile)
1313
1090
            print _("Could not read %s. Re-running with sudo") % cfgfile