62
from oslo.config import cfg
62
64
# If ../nova/__init__.py exists, add ../ to Python search path, so that
63
65
# it will override what happens to be installed in /usr/(local/)lib/python...
64
66
POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
72
74
from nova.api.ec2 import ec2utils
73
75
from nova import availability_zones
74
76
from nova.compute import instance_types
75
from nova.compute import rpcapi as compute_rpcapi
76
77
from nova import config
77
78
from nova import context
78
79
from nova import db
79
80
from nova.db import migration
80
81
from nova import exception
81
from nova.openstack.common import cfg
82
82
from nova.openstack.common import cliutils
83
from nova.openstack.common.db.sqlalchemy import session as db_session
83
84
from nova.openstack.common import importutils
84
85
from nova.openstack.common import log as logging
85
86
from nova.openstack.common import rpc
86
87
from nova.openstack.common import timeutils
87
88
from nova import quota
88
89
from nova.scheduler import rpcapi as scheduler_rpcapi
90
from nova import servicegroup
89
91
from nova import utils
90
92
from nova import version
93
95
CONF.import_opt('network_manager', 'nova.service')
94
CONF.import_opt('service_down_time', 'nova.config')
96
CONF.import_opt('service_down_time', 'nova.service')
95
97
CONF.import_opt('flat_network_bridge', 'nova.network.manager')
96
98
CONF.import_opt('num_networks', 'nova.network.manager')
97
99
CONF.import_opt('multi_host', 'nova.network.manager')
98
100
CONF.import_opt('network_size', 'nova.network.manager')
99
101
CONF.import_opt('vlan_start', 'nova.network.manager')
100
102
CONF.import_opt('vpn_start', 'nova.network.manager')
101
CONF.import_opt('default_floating_pool', 'nova.network.manager')
103
CONF.import_opt('default_floating_pool', 'nova.network.floating_ips')
102
104
CONF.import_opt('public_interface', 'nova.network.linux_net')
104
106
QUOTAS = quota.QUOTAS
206
208
@args('--path', dest='path', metavar='<path>', help='Script path')
207
209
def script(self, path):
208
"""Runs the script from the specifed path with flags set properly.
210
"""Runs the script from the specified path with flags set properly.
209
211
arguments: path"""
210
212
exec(compile(open(path).read(), path, 'exec'), locals(), globals())
226
228
@args('--key', dest="key", metavar='<key>', help='Key')
227
229
@args('--value', dest="value", metavar='<value>', help='Value')
228
230
def quota(self, project_id, key=None, value=None):
229
"""Set or display quotas for project"""
231
"""Set or display quotas for project."""
230
232
ctxt = context.get_admin_context()
231
233
project_quota = QUOTAS.get_project_quotas(ctxt, project_id)
232
234
if key and key in project_quota:
250
252
@args('--project', dest="project_id", metavar='<Project name>',
251
253
help='Project name')
252
254
def scrub(self, project_id):
253
"""Deletes data associated with project"""
255
"""Deletes data associated with project."""
254
256
admin_context = context.get_admin_context()
255
257
networks = db.project_get_networks(admin_context, project_id)
256
258
for network in networks:
269
271
@args('--host', dest="host", metavar='<host>', help='Host')
270
272
def list(self, host=None):
271
"""Lists all fixed ips (optionally by host)"""
273
"""Lists all fixed ips (optionally by host)."""
272
274
ctxt = context.get_admin_context()
382
383
@args('--interface', dest="interface", metavar='<interface>',
383
384
help='Optional interface')
384
385
def create(self, ip_range, pool=None, interface=None):
385
"""Creates floating ips for zone by range"""
386
"""Creates floating ips for zone by range."""
386
387
admin_context = context.get_admin_context()
388
389
pool = CONF.default_floating_pool
403
404
@args('--ip_range', dest="ip_range", metavar='<range>', help='IP range')
404
405
def delete(self, ip_range):
405
"""Deletes floating ips by range"""
406
"""Deletes floating ips by range."""
406
407
admin_context = context.get_admin_context()
408
409
ips = ({'address': str(address)}
476
477
gateway_v6=None, bridge=None, bridge_interface=None,
477
478
dns1=None, dns2=None, project_id=None, priority=None,
478
479
uuid=None, fixed_cidr=None):
479
"""Creates fixed ips for host by range"""
480
"""Creates fixed ips for host by range."""
480
481
kwargs = dict(((k, v) for k, v in locals().iteritems()
481
482
if v and k != "self"))
482
483
if multi_host is not None:
485
486
net_manager.create_networks(context.get_admin_context(), **kwargs)
488
"""List all created networks"""
489
"""List all created networks."""
489
490
_fmt = "%-5s\t%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s"
490
491
print _fmt % (_('id'),
520
521
@args('--uuid', dest='uuid', metavar='<uuid>',
521
522
help='UUID of network to delete')
522
523
def delete(self, fixed_range=None, uuid=None):
523
"""Deletes a network"""
524
"""Deletes a network."""
525
526
if fixed_range is None and uuid is None:
526
527
raise Exception(_("Please specify either fixed_range or uuid"))
560
561
#1) Associate (set not None value given by project/host parameter)
561
562
#2) Disassociate (set None by disassociate parameter)
562
563
#3) Keep unchanged (project/host key is not added to 'net')
565
net['project_id'] = None
569
# The --disassociate-X are boolean options, but if they user
570
# mistakenly provides a value, it will be used as a positional argument
571
# and be erroneously interepreted as some other parameter (e.g.
572
# a project instead of host value). The safest thing to do is error-out
573
# with a message indicating that there is probably a problem with
574
# how the disassociate modifications are being used.
575
if dis_project or dis_host:
577
error_msg = "ERROR: Unexpected arguments provided. Please " \
578
"use separate commands."
581
db.network_update(admin_context, network['id'], net)
564
585
net['project_id'] = project
566
net['project_id'] = None
568
587
net['host'] = host
571
589
db.network_update(admin_context, network['id'], net)
577
595
@args('--host', dest="host", metavar='<host>', help='Host')
578
596
def list(self, host=None):
579
"""Show a list of all instances"""
597
"""Show a list of all instances."""
581
599
print ("%-10s %-15s %-10s %-10s %-26s %-9s %-9s %-9s"
582
600
" %-10s %-10s %-10s %-5s" % (_('instance'),
617
635
class ServiceCommands(object):
618
"""Enable and disable running services"""
636
"""Enable and disable running services."""
620
638
@args('--host', dest='host', metavar='<host>', help='Host')
621
639
@args('--service', dest='service', metavar='<service>',
625
643
Show a list of all running services. Filter by host & service name.
645
servicegroup_api = servicegroup.API()
627
646
ctxt = context.get_admin_context()
628
647
now = timeutils.utcnow()
629
648
services = db.service_get_all(ctxt)
630
services = availability_zone.set_availability_zones(ctxt, services)
649
services = availability_zones.set_availability_zones(ctxt, services)
632
651
services = [s for s in services if s['host'] == host]
655
673
@args('--service', dest='service', metavar='<service>',
656
674
help='Nova service')
657
675
def enable(self, host, service):
658
"""Enable scheduling for a service"""
676
"""Enable scheduling for a service."""
659
677
ctxt = context.get_admin_context()
660
678
svc = db.service_get_by_args(ctxt, host, service)
667
685
@args('--service', dest='service', metavar='<service>',
668
686
help='Nova service')
669
687
def disable(self, host, service):
670
"""Disable scheduling for a service"""
688
"""Disable scheduling for a service."""
671
689
ctxt = context.get_admin_context()
672
690
svc = db.service_get_by_args(ctxt, host, service)
741
759
print "%-25s\t%-15s" % (_('host'),
743
761
ctxt = context.get_admin_context()
744
now = timeutils.utcnow()
745
762
services = db.service_get_all(ctxt)
746
763
services = availability_zones.set_availability_zones(ctxt, services)
771
788
"""Print the current database version."""
772
789
print migration.db_version()
791
@args('--max_rows', dest='max_rows', metavar='<number>',
792
help='Maximum number of deleted rows to archive')
793
def archive_deleted_rows(self, max_rows=None):
794
"""Move up to max_rows deleted rows from production tables to shadow
797
if max_rows is not None:
798
max_rows = int(max_rows)
799
admin_context = context.get_admin_context()
800
db.archive_deleted_rows(admin_context, max_rows)
775
803
class InstanceTypeCommands(object):
776
804
"""Class for managing instance types / flavors."""
778
806
def _print_instance_types(self, name, val):
779
deleted = ('', ', inactive')[val["deleted"] == 1]
780
807
is_public = ('private', 'public')[val["is_public"] == 1]
781
808
print ("%s: Memory: %sMB, VCPUS: %s, Root: %sGB, Ephemeral: %sGb, "
782
809
"FlavorID: %s, Swap: %sMB, RXTX Factor: %s, %s, ExtraSpecs %s") % (
802
829
help='Make flavor accessible to the public')
803
830
def create(self, name, memory, vcpus, root_gb, ephemeral_gb=0,
804
831
flavorid=None, swap=0, rxtx_factor=1.0, is_public=True):
805
"""Creates instance types / flavors"""
832
"""Creates instance types / flavors."""
807
834
instance_types.create(name, memory, vcpus, root_gb,
808
835
ephemeral_gb, flavorid, swap, rxtx_factor,
828
855
@args('--name', dest='name', metavar='<name>',
829
856
help='Name of instance type/flavor')
830
857
def delete(self, name):
831
"""Marks instance types / flavors as deleted"""
858
"""Marks instance types / flavors as deleted."""
833
860
instance_types.destroy(name)
834
861
except exception.InstanceTypeNotFound:
835
862
print _("Valid instance type name is required")
837
except exception.DBError, e:
864
except db_session.DBError, e:
838
865
print _("DB Error: %s") % e
840
867
except Exception:
845
872
@args('--name', dest='name', metavar='<name>',
846
873
help='Name of instance type/flavor')
847
874
def list(self, name=None):
848
"""Lists all active or specific instance types / flavors"""
875
"""Lists all active or specific instance types / flavors."""
851
878
inst_types = instance_types.get_all_types()
853
880
inst_types = instance_types.get_instance_type_by_name(name)
854
except exception.DBError, e:
881
except db_session.DBError, e:
856
883
if isinstance(inst_types.values()[0], dict):
857
884
for k, v in inst_types.iteritems():
866
893
@args('--value', dest='value', metavar='<value>',
867
894
help='The value of the key/value pair')
868
895
def set_key(self, name, key, value=None):
869
"""Add key/value pair to specified instance type's extra_specs"""
896
"""Add key/value pair to specified instance type's extra_specs."""
872
899
inst_type = instance_types.get_instance_type_by_name(name)
883
910
print _("Key %(key)s set to %(value)s on instance"
884
911
" type %(name)s") % locals()
885
except exception.DBError, e:
912
except db_session.DBError, e:
888
915
@args('--name', dest='name', metavar='<name>',
890
917
@args('--key', dest='key', metavar='<key>',
891
918
help='The key to be deleted')
892
919
def unset_key(self, name, key):
893
"""Delete the specified extra spec for instance type"""
920
"""Delete the specified extra spec for instance type."""
896
923
inst_type = instance_types.get_instance_type_by_name(name)
972
999
class GetLogCommands(object):
973
"""Get logging information"""
1000
"""Get logging information."""
975
1002
def errors(self):
976
"""Get all of the errors from the log files"""
1003
"""Get all of the errors from the log files."""
978
1005
if CONF.log_dir:
979
1006
logs = [x for x in os.listdir(CONF.log_dir) if x.endswith('.log')]
994
1021
print _('No errors in logfiles!')
996
1023
def syslog(self, num_entries=10):
997
"""Get <num_entries> of the nova syslog events"""
1024
"""Get <num_entries> of the nova syslog events."""
998
1025
entries = int(num_entries)
1059
1086
ctxt = context.get_admin_context()
1060
1087
db.cell_create(ctxt, values)
1062
@args('--cell_id', dest='cell_id', metavar='<cell_id>',
1063
help='ID of the cell to delete')
1064
def delete(self, cell_id):
1089
@args('--cell_name', dest='cell_name', metavar='<cell_name>',
1090
help='Name of the cell to delete')
1091
def delete(self, cell_name):
1065
1092
ctxt = context.get_admin_context()
1066
db.cell_delete(ctxt, cell_id)
1093
db.cell_delete(ctxt, cell_name)
1068
1095
def list(self):
1069
1096
ctxt = context.get_admin_context()
1132
1159
action_kwargs = []
1133
1160
for args, kwargs in getattr(action_fn, 'args', []):
1134
action_kwargs.append(kwargs['dest'])
1135
kwargs['dest'] = 'action_kwarg_' + kwargs['dest']
1161
if kwargs['dest'].startswith('action_kwarg_'):
1162
action_kwargs.append(
1163
kwargs['dest'][len('action_kwarg_'):])
1165
action_kwargs.append(kwargs['dest'])
1166
kwargs['dest'] = 'action_kwarg_' + kwargs['dest']
1136
1168
parser.add_argument(*args, **kwargs)
1138
1170
parser.set_defaults(action_fn=action_fn)