summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authordanwent@gmail.com <>2011-08-28 20:06:55 -0700
committerdanwent@gmail.com <>2011-08-28 20:06:55 -0700
commita4bd14f86f31ea82daad8e194b26e86e6dd37398 (patch)
tree3807a1131dc6a7ba7119782f356eb365f28d8b6c /bin
parent605fe4f19af3af830a2a8c82809e9ce5909c602d (diff)
parent0ef2581749f39fa4fd41c2376186418e730f0afb (diff)
downloadnova-a4bd14f86f31ea82daad8e194b26e86e6dd37398.tar.gz
nova-a4bd14f86f31ea82daad8e194b26e86e6dd37398.tar.xz
nova-a4bd14f86f31ea82daad8e194b26e86e6dd37398.zip
merge trunk
Diffstat (limited to 'bin')
-rwxr-xr-xbin/nova-api1
-rwxr-xr-xbin/nova-api-ec21
-rwxr-xr-xbin/nova-api-os1
-rwxr-xr-xbin/nova-compute1
-rwxr-xr-xbin/nova-manage530
-rwxr-xr-xbin/nova-network1
-rwxr-xr-xbin/nova-objectstore1
-rwxr-xr-xbin/nova-scheduler3
-rwxr-xr-xbin/nova-volume1
-rwxr-xr-xbin/nova-vsa49
10 files changed, 579 insertions, 10 deletions
diff --git a/bin/nova-api b/bin/nova-api
index 38e2624d8..d8635978e 100755
--- a/bin/nova-api
+++ b/bin/nova-api
@@ -45,6 +45,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
servers = []
for api in flags.FLAGS.enabled_apis:
servers.append(service.WSGIService(api))
diff --git a/bin/nova-api-ec2 b/bin/nova-api-ec2
index df50f713d..9f82a69e4 100755
--- a/bin/nova-api-ec2
+++ b/bin/nova-api-ec2
@@ -41,6 +41,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
server = service.WSGIService('ec2')
service.serve(server)
service.wait()
diff --git a/bin/nova-api-os b/bin/nova-api-os
index 374e850ea..83a808987 100755
--- a/bin/nova-api-os
+++ b/bin/nova-api-os
@@ -41,6 +41,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
server = service.WSGIService('osapi')
service.serve(server)
service.wait()
diff --git a/bin/nova-compute b/bin/nova-compute
index 5239fae72..0c69a8129 100755
--- a/bin/nova-compute
+++ b/bin/nova-compute
@@ -43,6 +43,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
server = service.Service.create(binary='nova-compute')
service.serve(server)
service.wait()
diff --git a/bin/nova-manage b/bin/nova-manage
index 0c2cee3ce..a95890e36 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -53,6 +53,7 @@
CLI interface for nova management.
"""
+import ast
import gettext
import glob
import json
@@ -85,11 +86,13 @@ from nova import quota
from nova import rpc
from nova import utils
from nova import version
+from nova import vsa
from nova.api.ec2 import ec2utils
from nova.auth import manager
from nova.cloudpipe import pipelib
from nova.compute import instance_types
from nova.db import migration
+from nova.volume import volume_types
FLAGS = flags.FLAGS
flags.DECLARE('fixed_range', 'nova.network.manager')
@@ -134,7 +137,7 @@ class VpnCommands(object):
help='Project name')
def list(self, project=None):
"""Print a listing of the VPN data for one or all projects."""
-
+ print "WARNING: This method only works with deprecated auth"
print "%-12s\t" % 'project',
print "%-20s\t" % 'ip:port',
print "%-20s\t" % 'private_ip',
@@ -170,17 +173,22 @@ class VpnCommands(object):
def spawn(self):
"""Run all VPNs."""
+ print "WARNING: This method only works with deprecated auth"
for p in reversed(self.manager.get_projects()):
if not self._vpn_for(p.id):
print 'spawning %s' % p.id
- self.pipe.launch_vpn_instance(p.id)
+ self.pipe.launch_vpn_instance(p.id, p.project_manager_id)
time.sleep(10)
@args('--project', dest="project_id", metavar='<Project name>',
help='Project name')
- def run(self, project_id):
- """Start the VPN for a given project."""
- self.pipe.launch_vpn_instance(project_id)
+ @args('--user', dest="user_id", metavar='<user name>', help='User name')
+ def run(self, project_id, user_id):
+ """Start the VPN for a given project and user."""
+ if not user_id:
+ print "WARNING: This method only works with deprecated auth"
+ user_id = self.manager.get_project(project_id).project_manager_id
+ self.pipe.launch_vpn_instance(project_id, user_id)
@args('--project', dest="project_id", metavar='<Project name>',
help='Project name')
@@ -195,10 +203,6 @@ class VpnCommands(object):
"""
# TODO(tr3buchet): perhaps this shouldn't update all networks
# associated with a project in the future
- project = self.manager.get_project(project_id)
- if not project:
- print 'No project %s' % (project_id)
- return
admin_context = context.get_admin_context()
networks = db.project_get_networks(admin_context, project_id)
for network in networks:
@@ -825,6 +829,39 @@ class NetworkCommands(object):
uuid=None)
+ @args('--network', dest="fixed_range", metavar='<x.x.x.x/yy>',
+ help='Network to modify')
+ @args('--project', dest="project", metavar='<project name>',
+ help='Project name to associate')
+ @args('--host', dest="host", metavar='<host>',
+ help='Host to associate')
+ @args('--disassociate-project', action="store_true", dest='dis_project',
+ default=False, help='Disassociate Network from Project')
+ @args('--disassociate-host', action="store_true", dest='dis_host',
+ default=False, help='Disassociate Host from Project')
+ def modify(self, fixed_range, project=None, host=None,
+ dis_project=None, dis_host=None):
+ """Associate/Disassociate Network with Project and/or Host
+ arguments: network project host
+ leave any field blank to ignore it
+ """
+ admin_context = context.get_admin_context()
+ network = db.network_get_by_cidr(admin_context, fixed_range)
+ net = {}
+ #User can choose the following actions each for project and host.
+ #1) Associate (set not None value given by project/host parameter)
+ #2) Disassociate (set None by disassociate parameter)
+ #3) Keep unchanged (project/host key is not added to 'net')
+ if project:
+ net['project_id'] = project
+ elif dis_project:
+ net['project_id'] = None
+ if host:
+ net['host'] = host
+ elif dis_host:
+ net['host'] = None
+ db.network_update(admin_context, network['id'], net)
+
class VmCommands(object):
"""Class for mangaging VM instances."""
@@ -1091,6 +1128,477 @@ class VersionCommands(object):
self.list()
+class VsaCommands(object):
+ """Methods for dealing with VSAs"""
+
+ def __init__(self, *args, **kwargs):
+ self.manager = manager.AuthManager()
+ self.vsa_api = vsa.API()
+ self.context = context.get_admin_context()
+
+ self._format_str_vsa = "%(id)-5s %(vsa_id)-15s %(name)-25s "\
+ "%(type)-10s %(vcs)-6s %(drives)-9s %(stat)-10s "\
+ "%(az)-10s %(time)-10s"
+ self._format_str_volume = "\t%(id)-4s %(name)-15s %(size)-5s "\
+ "%(stat)-10s %(att)-20s %(time)s"
+ self._format_str_drive = "\t%(id)-4s %(name)-15s %(size)-5s "\
+ "%(stat)-10s %(host)-20s %(type)-4s %(tname)-10s %(time)s"
+ self._format_str_instance = "\t%(id)-4s %(name)-10s %(dname)-20s "\
+ "%(image)-12s %(type)-10s %(fl_ip)-15s %(fx_ip)-15s "\
+ "%(stat)-10s %(host)-15s %(time)s"
+
+ def _print_vsa_header(self):
+ print self._format_str_vsa %\
+ dict(id=_('ID'),
+ vsa_id=_('vsa_id'),
+ name=_('displayName'),
+ type=_('vc_type'),
+ vcs=_('vc_cnt'),
+ drives=_('drive_cnt'),
+ stat=_('status'),
+ az=_('AZ'),
+ time=_('createTime'))
+
+ def _print_vsa(self, vsa):
+ print self._format_str_vsa %\
+ dict(id=vsa['id'],
+ vsa_id=vsa['name'],
+ name=vsa['display_name'],
+ type=vsa['vsa_instance_type'].get('name', None),
+ vcs=vsa['vc_count'],
+ drives=vsa['vol_count'],
+ stat=vsa['status'],
+ az=vsa['availability_zone'],
+ time=str(vsa['created_at']))
+
+ def _print_volume_header(self):
+ print _(' === Volumes ===')
+ print self._format_str_volume %\
+ dict(id=_('ID'),
+ name=_('name'),
+ size=_('size'),
+ stat=_('status'),
+ att=_('attachment'),
+ time=_('createTime'))
+
+ def _print_volume(self, vol):
+ print self._format_str_volume %\
+ dict(id=vol['id'],
+ name=vol['display_name'] or vol['name'],
+ size=vol['size'],
+ stat=vol['status'],
+ att=vol['attach_status'],
+ time=str(vol['created_at']))
+
+ def _print_drive_header(self):
+ print _(' === Drives ===')
+ print self._format_str_drive %\
+ dict(id=_('ID'),
+ name=_('name'),
+ size=_('size'),
+ stat=_('status'),
+ host=_('host'),
+ type=_('type'),
+ tname=_('typeName'),
+ time=_('createTime'))
+
+ def _print_drive(self, drive):
+ if drive['volume_type_id'] is not None and drive.get('volume_type'):
+ drive_type_name = drive['volume_type'].get('name')
+ else:
+ drive_type_name = ''
+
+ print self._format_str_drive %\
+ dict(id=drive['id'],
+ name=drive['display_name'],
+ size=drive['size'],
+ stat=drive['status'],
+ host=drive['host'],
+ type=drive['volume_type_id'],
+ tname=drive_type_name,
+ time=str(drive['created_at']))
+
+ def _print_instance_header(self):
+ print _(' === Instances ===')
+ print self._format_str_instance %\
+ dict(id=_('ID'),
+ name=_('name'),
+ dname=_('disp_name'),
+ image=_('image'),
+ type=_('type'),
+ fl_ip=_('floating_IP'),
+ fx_ip=_('fixed_IP'),
+ stat=_('status'),
+ host=_('host'),
+ time=_('createTime'))
+
+ def _print_instance(self, vc):
+
+ fixed_addr = None
+ floating_addr = None
+ if vc['fixed_ips']:
+ fixed = vc['fixed_ips'][0]
+ fixed_addr = fixed['address']
+ if fixed['floating_ips']:
+ floating_addr = fixed['floating_ips'][0]['address']
+ floating_addr = floating_addr or fixed_addr
+
+ print self._format_str_instance %\
+ dict(id=vc['id'],
+ name=ec2utils.id_to_ec2_id(vc['id']),
+ dname=vc['display_name'],
+ image=('ami-%08x' % int(vc['image_ref'])),
+ type=vc['instance_type']['name'],
+ fl_ip=floating_addr,
+ fx_ip=fixed_addr,
+ stat=vc['state_description'],
+ host=vc['host'],
+ time=str(vc['created_at']))
+
+ def _list(self, context, vsas, print_drives=False,
+ print_volumes=False, print_instances=False):
+ if vsas:
+ self._print_vsa_header()
+
+ for vsa in vsas:
+ self._print_vsa(vsa)
+ vsa_id = vsa.get('id')
+
+ if print_instances:
+ instances = self.vsa_api.get_all_vsa_instances(context, vsa_id)
+ if instances:
+ print
+ self._print_instance_header()
+ for instance in instances:
+ self._print_instance(instance)
+ print
+
+ if print_drives:
+ drives = self.vsa_api.get_all_vsa_drives(context, vsa_id)
+ if drives:
+ self._print_drive_header()
+ for drive in drives:
+ self._print_drive(drive)
+ print
+
+ if print_volumes:
+ volumes = self.vsa_api.get_all_vsa_volumes(context, vsa_id)
+ if volumes:
+ self._print_volume_header()
+ for volume in volumes:
+ self._print_volume(volume)
+ print
+
+ @args('--storage', dest='storage',
+ metavar="[{'drive_name': 'type', 'num_drives': N, 'size': M},..]",
+ help='Initial storage allocation for VSA')
+ @args('--name', dest='name', metavar="<name>", help='VSA name')
+ @args('--description', dest='description', metavar="<description>",
+ help='VSA description')
+ @args('--vc', dest='vc_count', metavar="<number>", help='Number of VCs')
+ @args('--instance_type', dest='instance_type_name', metavar="<name>",
+ help='Instance type name')
+ @args('--image', dest='image_name', metavar="<name>", help='Image name')
+ @args('--shared', dest='shared', action="store_true", default=False,
+ help='Use shared drives')
+ @args('--az', dest='az', metavar="<zone:host>", help='Availability zone')
+ @args('--user', dest="user_id", metavar='<User name>',
+ help='User name')
+ @args('--project', dest="project_id", metavar='<Project name>',
+ help='Project name')
+ def create(self, storage='[]', name=None, description=None, vc_count=1,
+ instance_type_name=None, image_name=None, shared=None,
+ az=None, user_id=None, project_id=None):
+ """Create a VSA."""
+
+ if project_id is None:
+ try:
+ project_id = os.getenv("EC2_ACCESS_KEY").split(':')[1]
+ except Exception as exc:
+ print _("Failed to retrieve project id: %(exc)s") % exc
+ raise
+
+ if user_id is None:
+ try:
+ project = self.manager.get_project(project_id)
+ user_id = project.project_manager_id
+ except Exception as exc:
+ print _("Failed to retrieve user info: %(exc)s") % exc
+ raise
+
+ is_admin = self.manager.is_admin(user_id)
+ ctxt = context.RequestContext(user_id, project_id, is_admin)
+ if not is_admin and \
+ not self.manager.is_project_member(user_id, project_id):
+ msg = _("%(user_id)s must be an admin or a "
+ "member of %(project_id)s")
+ LOG.warn(msg % locals())
+ raise ValueError(msg % locals())
+
+ # Sanity check for storage string
+ storage_list = []
+ if storage is not None:
+ try:
+ storage_list = ast.literal_eval(storage)
+ except:
+ print _("Invalid string format %s") % storage
+ raise
+
+ for node in storage_list:
+ if ('drive_name' not in node) or ('num_drives' not in node):
+ print (_("Invalid string format for element %s. " \
+ "Expecting keys 'drive_name' & 'num_drives'"),
+ str(node))
+ raise KeyError
+
+ if instance_type_name == '':
+ instance_type_name = None
+ instance_type = instance_types.get_instance_type_by_name(
+ instance_type_name)
+
+ if image_name == '':
+ image_name = None
+
+ if shared in [None, False, "--full_drives"]:
+ shared = False
+ elif shared in [True, "--shared"]:
+ shared = True
+ else:
+ raise ValueError(_('Shared parameter should be set either to "\
+ "--shared or --full_drives'))
+
+ values = {
+ 'display_name': name,
+ 'display_description': description,
+ 'vc_count': int(vc_count),
+ 'instance_type': instance_type,
+ 'image_name': image_name,
+ 'availability_zone': az,
+ 'storage': storage_list,
+ 'shared': shared,
+ }
+
+ result = self.vsa_api.create(ctxt, **values)
+ self._list(ctxt, [result])
+
+ @args('--id', dest='vsa_id', metavar="<vsa_id>", help='VSA ID')
+ @args('--name', dest='name', metavar="<name>", help='VSA name')
+ @args('--description', dest='description', metavar="<description>",
+ help='VSA description')
+ @args('--vc', dest='vc_count', metavar="<number>", help='Number of VCs')
+ def update(self, vsa_id, name=None, description=None, vc_count=None):
+ """Updates name/description of vsa and number of VCs."""
+
+ values = {}
+ if name is not None:
+ values['display_name'] = name
+ if description is not None:
+ values['display_description'] = description
+ if vc_count is not None:
+ values['vc_count'] = int(vc_count)
+
+ vsa_id = ec2utils.ec2_id_to_id(vsa_id)
+ result = self.vsa_api.update(self.context, vsa_id=vsa_id, **values)
+ self._list(self.context, [result])
+
+ @args('--id', dest='vsa_id', metavar="<vsa_id>", help='VSA ID')
+ def delete(self, vsa_id):
+ """Delete a VSA."""
+ vsa_id = ec2utils.ec2_id_to_id(vsa_id)
+ self.vsa_api.delete(self.context, vsa_id)
+
+ @args('--id', dest='vsa_id', metavar="<vsa_id>",
+ help='VSA ID (optional)')
+ @args('--all', dest='all', action="store_true", default=False,
+ help='Show all available details')
+ @args('--drives', dest='drives', action="store_true",
+ help='Include drive-level details')
+ @args('--volumes', dest='volumes', action="store_true",
+ help='Include volume-level details')
+ @args('--instances', dest='instances', action="store_true",
+ help='Include instance-level details')
+ def list(self, vsa_id=None, all=False,
+ drives=False, volumes=False, instances=False):
+ """Describe all available VSAs (or particular one)."""
+
+ vsas = []
+ if vsa_id is not None:
+ internal_id = ec2utils.ec2_id_to_id(vsa_id)
+ vsa = self.vsa_api.get(self.context, internal_id)
+ vsas.append(vsa)
+ else:
+ vsas = self.vsa_api.get_all(self.context)
+
+ if all:
+ drives = volumes = instances = True
+
+ self._list(self.context, vsas, drives, volumes, instances)
+
+ def update_capabilities(self):
+ """Forces updates capabilities on all nova-volume nodes."""
+
+ rpc.fanout_cast(context.get_admin_context(),
+ FLAGS.volume_topic,
+ {"method": "notification",
+ "args": {"event": "startup"}})
+
+
+class VsaDriveTypeCommands(object):
+ """Methods for dealing with VSA drive types"""
+
+ def __init__(self, *args, **kwargs):
+ super(VsaDriveTypeCommands, self).__init__(*args, **kwargs)
+ self.context = context.get_admin_context()
+ self._drive_type_template = '%s_%sGB_%sRPM'
+
+ def _list(self, drives):
+ format_str = "%-5s %-30s %-10s %-10s %-10s %-20s %-10s %s"
+ if len(drives):
+ print format_str %\
+ (_('ID'),
+ _('name'),
+ _('type'),
+ _('size_gb'),
+ _('rpm'),
+ _('capabilities'),
+ _('visible'),
+ _('createTime'))
+
+ for name, vol_type in drives.iteritems():
+ drive = vol_type.get('extra_specs')
+ print format_str %\
+ (str(vol_type['id']),
+ drive['drive_name'],
+ drive['drive_type'],
+ drive['drive_size'],
+ drive['drive_rpm'],
+ drive.get('capabilities', ''),
+ str(drive.get('visible', '')),
+ str(vol_type['created_at']))
+
+ @args('--type', dest='type', metavar="<type>",
+ help='Drive type (SATA, SAS, SSD, etc.)')
+ @args('--size', dest='size_gb', metavar="<gb>", help='Drive size in GB')
+ @args('--rpm', dest='rpm', metavar="<rpm>", help='RPM')
+ @args('--capabilities', dest='capabilities', default=None,
+ metavar="<string>", help='Different capabilities')
+ @args('--hide', dest='hide', action="store_true", default=False,
+ help='Show or hide drive')
+ @args('--name', dest='name', metavar="<name>", help='Drive name')
+ def create(self, type, size_gb, rpm, capabilities=None,
+ hide=False, name=None):
+ """Create drive type."""
+
+ hide = True if hide in [True, "True", "--hide", "hide"] else False
+
+ if name is None:
+ name = self._drive_type_template % (type, size_gb, rpm)
+
+ extra_specs = {'type': 'vsa_drive',
+ 'drive_name': name,
+ 'drive_type': type,
+ 'drive_size': size_gb,
+ 'drive_rpm': rpm,
+ 'visible': True,
+ }
+ if hide:
+ extra_specs['visible'] = False
+
+ if capabilities is not None and capabilities != '':
+ extra_specs['capabilities'] = capabilities
+
+ volume_types.create(self.context, name, extra_specs)
+ result = volume_types.get_volume_type_by_name(self.context, name)
+ self._list({name: result})
+
+ @args('--name', dest='name', metavar="<name>", help='Drive name')
+ @args('--purge', action="store_true", dest='purge', default=False,
+ help='purge record from database')
+ def delete(self, name, purge):
+ """Marks instance types / flavors as deleted"""
+ try:
+ if purge:
+ volume_types.purge(self.context, name)
+ verb = "purged"
+ else:
+ volume_types.destroy(self.context, name)
+ verb = "deleted"
+ except exception.ApiError:
+ print "Valid volume type name is required"
+ sys.exit(1)
+ except exception.DBError, e:
+ print "DB Error: %s" % e
+ sys.exit(2)
+ except:
+ sys.exit(3)
+ else:
+ print "%s %s" % (name, verb)
+
+ @args('--all', dest='all', action="store_true", default=False,
+ help='Show all drives (including invisible)')
+ @args('--name', dest='name', metavar="<name>",
+ help='Show only specified drive')
+ def list(self, all=False, name=None):
+ """Describe all available VSA drive types (or particular one)."""
+
+ all = False if all in ["--all", False, "False"] else True
+
+ search_opts = {'extra_specs': {'type': 'vsa_drive'}}
+ if name is not None:
+ search_opts['extra_specs']['name'] = name
+
+ if all == False:
+ search_opts['extra_specs']['visible'] = '1'
+
+ drives = volume_types.get_all_types(self.context,
+ search_opts=search_opts)
+ self._list(drives)
+
+ @args('--name', dest='name', metavar="<name>", help='Drive name')
+ @args('--type', dest='type', metavar="<type>",
+ help='Drive type (SATA, SAS, SSD, etc.)')
+ @args('--size', dest='size_gb', metavar="<gb>", help='Drive size in GB')
+ @args('--rpm', dest='rpm', metavar="<rpm>", help='RPM')
+ @args('--capabilities', dest='capabilities', default=None,
+ metavar="<string>", help='Different capabilities')
+ @args('--visible', dest='visible',
+ metavar="<show|hide>", help='Show or hide drive')
+ def update(self, name, type=None, size_gb=None, rpm=None,
+ capabilities=None, visible=None):
+ """Update drive type."""
+
+ volume_type = volume_types.get_volume_type_by_name(self.context, name)
+
+ extra_specs = {'type': 'vsa_drive'}
+
+ if type:
+ extra_specs['drive_type'] = type
+
+ if size_gb:
+ extra_specs['drive_size'] = size_gb
+
+ if rpm:
+ extra_specs['drive_rpm'] = rpm
+
+ if capabilities:
+ extra_specs['capabilities'] = capabilities
+
+ if visible is not None:
+ if visible in ["show", True, "True"]:
+ extra_specs['visible'] = True
+ elif visible in ["hide", False, "False"]:
+ extra_specs['visible'] = False
+ else:
+ raise ValueError(_('visible parameter should be set to '\
+ 'show or hide'))
+
+ db.api.volume_type_extra_specs_update_or_create(self.context,
+ volume_type['id'],
+ extra_specs)
+ result = volume_types.get_volume_type_by_name(self.context, name)
+ self._list({name: result})
+
+
class VolumeCommands(object):
"""Methods for dealing with a cloud in an odd state"""
@@ -1477,6 +1985,7 @@ CATEGORIES = [
('agent', AgentBuildCommands),
('config', ConfigCommands),
('db', DbCommands),
+ ('drive', VsaDriveTypeCommands),
('fixed', FixedIpCommands),
('flavor', InstanceTypeCommands),
('floating', FloatingIpCommands),
@@ -1492,7 +2001,8 @@ CATEGORIES = [
('version', VersionCommands),
('vm', VmCommands),
('volume', VolumeCommands),
- ('vpn', VpnCommands)]
+ ('vpn', VpnCommands),
+ ('vsa', VsaCommands)]
def lazy_match(name, key_value_tuples):
diff --git a/bin/nova-network b/bin/nova-network
index 57759d30a..0f1482515 100755
--- a/bin/nova-network
+++ b/bin/nova-network
@@ -43,6 +43,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
server = service.Service.create(binary='nova-network')
service.serve(server)
service.wait()
diff --git a/bin/nova-objectstore b/bin/nova-objectstore
index c7a76e120..757301c24 100755
--- a/bin/nova-objectstore
+++ b/bin/nova-objectstore
@@ -49,6 +49,7 @@ if __name__ == '__main__':
utils.default_flagfile()
FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
router = s3server.S3Application(FLAGS.buckets_path)
server = wsgi.Server("S3 Objectstore",
router,
diff --git a/bin/nova-scheduler b/bin/nova-scheduler
index 2e168cbc6..c1033a304 100755
--- a/bin/nova-scheduler
+++ b/bin/nova-scheduler
@@ -22,6 +22,7 @@
import eventlet
eventlet.monkey_patch()
+import gettext
import os
import sys
@@ -33,6 +34,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
sys.path.insert(0, possible_topdir)
+gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
@@ -43,6 +45,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
server = service.Service.create(binary='nova-scheduler')
service.serve(server)
service.wait()
diff --git a/bin/nova-volume b/bin/nova-volume
index 5405aebbb..8caa0f44a 100755
--- a/bin/nova-volume
+++ b/bin/nova-volume
@@ -43,6 +43,7 @@ if __name__ == '__main__':
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
+ utils.monkey_patch()
server = service.Service.create(binary='nova-volume')
service.serve(server)
service.wait()
diff --git a/bin/nova-vsa b/bin/nova-vsa
new file mode 100755
index 000000000..2d6eee2c0
--- /dev/null
+++ b/bin/nova-vsa
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Zadara Storage Inc.
+# Copyright (c) 2011 OpenStack LLC.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Starter script for Nova VSA."""
+
+import eventlet
+eventlet.monkey_patch()
+
+import os
+import sys
+
+# If ../nova/__init__.py exists, add ../ to Python search path, so that
+# it will override what happens to be installed in /usr/(local/)lib/python...
+possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
+ os.pardir,
+ os.pardir))
+if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
+ sys.path.insert(0, possible_topdir)
+
+
+from nova import flags
+from nova import log as logging
+from nova import service
+from nova import utils
+
+if __name__ == '__main__':
+ utils.default_flagfile()
+ flags.FLAGS(sys.argv)
+ logging.setup()
+ utils.monkey_patch()
+ server = service.Service.create(binary='nova-vsa')
+ service.serve(server)
+ service.wait()