92
88
from nova import utils
93
89
from nova import version
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')
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')
105
103
QUOTAS = quota.QUOTAS
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()
226
project_quota = QUOTAS.get_project_quotas(ctxt, project_id)
227
if key and key in project_quota:
229
228
if value.lower() == 'unlimited':
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)
235
print _('%(key)s is not a valid quota key. Valid options are: '
236
'%(options)s.') % {'key': key,
237
'options': ', '.join(project_quota)}
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:
778
class VolumeCommands(object):
779
"""Methods for dealing with a cloud in an odd state"""
781
@args('--volume', dest='volume_id', metavar='<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."""
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"))
795
ctxt = context.get_admin_context()
796
volume = db.volume_get(ctxt, param2id(volume_id))
797
host = volume['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)
805
if volume['status'] == 'in-use':
806
print "Volume is in-use."
807
print "Detach volume from instance and then try again."
811
rpc.queue_get_for(ctxt, FLAGS.volume_topic, host),
812
{"method": "delete_volume",
813
"args": {"volume_id": volume['id']}})
815
@args('--volume', dest='volume_id', metavar='<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."""
822
if 'cinder' in FLAGS.volume_api_class:
823
print(_("\"nova-manage volume reattach\" only valid "
824
"when using nova-volume service"))
827
ctxt = context.get_admin_context()
828
volume = db.volume_get(ctxt, param2id(volume_id))
830
if not volume['instance_id']:
831
print "volume is not attached to an instance"
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'])
839
782
class InstanceTypeCommands(object):
840
783
"""Class for managing instance types / flavors."""
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"""
871
814
instance_types.create(name, memory, vcpus, root_gb,
872
815
ephemeral_gb, flavorid, swap, rxtx_factor,
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")
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 "
825
print _("Currently defined instance_type names and flavorids:")
885
829
except Exception:
886
print "Unknown error"
830
print _("Unknown error")
889
print "%s created" % name
833
print _("%s created") % name
891
835
@args('--name', dest='name', metavar='<name>',
892
836
help='Name of instance type/flavor')
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")
900
844
except exception.DBError, e:
901
print "DB Error: %s" % e
845
print _("DB Error: %s") % e
903
847
except Exception:
906
print "%s deleted" % name
850
print _("%s deleted") % name
908
852
@args('--name', dest='name', metavar='<name>',
909
853
help='Name of instance type/flavor')
975
class StorageManagerCommands(object):
976
"""Class for mangaging Storage Backends and Flavors"""
978
def flavor_list(self, flavor=None):
979
ctxt = context.get_admin_context()
983
flavors = db.sm_flavor_get_all(ctxt)
985
flavors = db.sm_flavor_get(ctxt, flavor)
986
except exception.NotFound as ex:
987
print "error: %s" % ex
990
print "%-18s\t%-20s\t%s" % (_('id'),
995
print "%-18s\t%-20s\t%s" % (
1000
def flavor_create(self, label, desc):
1001
# TODO(renukaapte) flavor name must be unique
1003
db.sm_flavor_create(context.get_admin_context(),
1006
except exception.DBError, e:
1009
def flavor_delete(self, label):
1011
db.sm_flavor_delete(context.get_admin_context(), label)
1013
except exception.DBError, e:
1016
def _splitfun(self, item):
1020
def backend_list(self, backend_conf_id=None):
1021
ctxt = context.get_admin_context()
1024
if backend_conf_id is None:
1025
backends = db.sm_backend_conf_get_all(ctxt)
1027
backends = db.sm_backend_conf_get(ctxt, backend_conf_id)
1029
except exception.NotFound as ex:
1030
print "error: %s" % ex
1033
print "%-5s\t%-10s\t%-40s\t%-10s\t%s" % (_('id'),
1037
_('Config Parameters'),)
1040
print "%-5s\t%-10s\t%-40s\t%-10s\t%s" % (b['id'],
1044
b['config_params'],)
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))
1051
if 'sr_uuid' in params:
1053
backend = db.sm_backend_conf_get_by_sr(ctxt,
1055
except exception.DBError, e:
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':
1064
db.sm_backend_conf_update(ctxt, backend['id'],
1065
dict(created=False))
1066
except exception.DBError, e:
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':
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"
1085
flavors = db.sm_flavor_get_by_label(ctxt, flavor_label)
1086
except exception.NotFound as ex:
1087
print "error: %s" % ex
1090
config_params = "".join(['%s=%s ' %
1091
(key, params[key]) for key in params])
1094
db.sm_backend_conf_create(ctxt,
1095
dict(flavor_id=flavors['id'],
1098
config_params=config_params))
1099
except exception.DBError, e:
1102
def backend_remove(self, backend_conf_id):
1104
db.sm_backend_conf_delete(context.get_admin_context(),
1107
except exception.DBError, e:
1111
919
class AgentBuildCommands(object):
1112
920
"""Class for managing agent builds."""
1168
976
'md5hash': md5hash})
1171
class ConfigCommands(object):
1172
"""Class for exposing the flags defined by flag_file(s)."""
1178
for key, value in FLAGS.iteritems():
1179
if value is not None:
1180
print '%s = %s' % (key, value)
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()
1194
with open(outfile, 'w') as configfile:
1195
configfile.write(config)
1200
979
class GetLogCommands(object):
1201
980
"""Get logging information"""
1203
982
def errors(self):
1204
983
"""Get all of the errors from the log files"""
1207
logs = [x for x in os.listdir(FLAGS.logdir) if x.endswith('.log')]
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")]
1246
print "No nova entries in syslog!"
1026
print _('No nova entries in syslog!')
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),