diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 00000000000..d1ebd5ecab8 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,17 @@ +If you would like to contribute to the development of OpenStack, +you must follow the steps in the "If you're a developer, start here" +section of this page: + + http://wiki.openstack.org/HowToContribute + +Once those steps have been completed, changes to OpenStack +should be submitted for review via the Gerrit tool, following +the workflow documented at: + + http://wiki.openstack.org/GerritWorkflow + +Pull requests submitted through GitHub will be ignored. + +Bugs should be filed on Launchpad, not GitHub: + + https://bugs.launchpad.net/nova diff --git a/HACKING.rst b/HACKING.rst index 52dc38bf88d..082beb87d7e 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -9,6 +9,7 @@ Nova Style Commandments General ------- - Put two newlines between top-level code (funcs, classes, etc) +- Use only UNIX style newlines ("\n"), not Windows style ("\r\n") - Put one newline between methods in classes and anywhere else - Long lines should be wrapped in parentheses in preference to using a backslash for line continuation. @@ -27,12 +28,33 @@ General mylist = Foo().list() # OKAY, does not shadow built-in +- Use the "is not" operator when testing for unequal identities. Example:: + + if not X is Y: # BAD, intended behavior is ambiguous + pass + + if X is not Y: # OKAY, intuitive + pass + +- Use the "not in" operator for evaluating membership in a collection. Example:: + + if not X in Y: # BAD, intended behavior is ambiguous + pass + + if X not in Y: # OKAY, intuitive + pass + + if not (X in Y or X in Z): # OKAY, still better than all those 'not's + pass + Imports ------- - Do not import objects, only modules (*) - Do not import more than one module per line (*) +- Do not use wildcard ``*`` import (*) - Do not make relative imports +- Do not make new nova.db imports in nova/virt/* - Order your imports by the full module path - Organize your imports according to the following template @@ -41,6 +63,7 @@ Imports - imports from ``migrate`` package - imports from ``sqlalchemy`` package - imports from ``nova.db.sqlalchemy.session`` module +- imports from ``nova.db.sqlalchemy.migration.versioning_api`` package Example:: @@ -188,6 +211,25 @@ Example:: LOG.error(msg % {"s_id": "1234", "m_key": "imageId"}) +Python 3.x compatibility +------------------------ +Nova code should stay Python 3.x compatible. That means all Python 2.x-only +constructs should be avoided. An example is + + except x,y: + +Use + + except x as y: + +instead. Other Python 3.x compatility issues, like e.g. print operator +can be avoided in new code by using + + from __future__ import print_function + +at the top of your module. + + Creating Unit Tests ------------------- For every new feature, unit tests should be created that both test and @@ -197,27 +239,68 @@ submitted bug fix does have a unit test, be sure to add a new one that fails without the patch and passes with the patch. For more information on creating unit tests and utilizing the testing -infrastructure in OpenStack Nova, please read nova/testing/README.rst. - - -openstack-common +infrastructure in OpenStack Nova, please read nova/tests/README.rst. + + +Running Tests +------------- +The testing system is based on a combination of tox and testr. The canonical +approach to running tests is to simply run the command `tox`. This will +create virtual environments, populate them with depenedencies and run all of +the tests that OpenStack CI systems run. Behind the scenes, tox is running +`testr run --parallel`, but is set up such that you can supply any additional +testr arguments that are needed to tox. For example, you can run: +`tox -- --analyze-isolation` to cause tox to tell testr to add +--analyze-isolation to its argument list. + +It is also possible to run the tests inside of a virtual environment +you have created, or it is possible that you have all of the dependencies +installed locally already. In this case, you can interact with the testr +command directly. Running `testr run` will run the entire test suite. `testr +run --parallel` will run it in parallel (this is the default incantation tox +uses.) More information about testr can be found at: +http://wiki.openstack.org/testr + +Building Docs +------------- +Normal Sphinx docs can be built via the setuptools `build_sphinx` command. To +do this via `tox`, simply run `tox -evenv -- python setup.py build_sphinx`, +which will cause a virtualenv with all of the needed dependencies to be +created and then inside of the virtualenv, the docs will be created and +put into doc/build/html. + +If you'd like a PDF of the documentation, you'll need LaTeX installed, and +additionally some fonts. On Ubuntu systems, you can get what you need with:: + + apt-get install texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended + +Then run `build_sphinx_latex`, change to the build dir and run `make`. +Like so:: + + tox -evenv -- python setup.py build_sphinx_latex + cd build/sphinx/latex + make + +You should wind up with a PDF - Nova.pdf. + +oslo-incubator ---------------- -A number of modules from openstack-common are imported into the project. +A number of modules from oslo-incubator are imported into the project. -These modules are "incubating" in openstack-common and are kept in sync -with the help of openstack-common's update.py script. See: +These modules are "incubating" in oslo-incubator and are kept in sync +with the help of oslo's update.py script. See: - http://wiki.openstack.org/CommonLibrary#Incubation + https://wiki.openstack.org/wiki/Oslo#Incubation The copy of the code should never be directly modified here. Please -always update openstack-common first and then run the script to copy +always update oslo-incubator first and then run the script to copy the changes across. OpenStack Trademark ------------------- -OpenStack is a registered trademark of OpenStack, LLC, and uses the +OpenStack is a registered trademark of the OpenStack Foundation, and uses the following capitalization: OpenStack @@ -228,8 +311,8 @@ Commit Messages Using a common format for commit messages will help keep our git history readable. Follow these guidelines: - First, provide a brief summary (it is recommended to keep the commit title - under 50 chars). + First, provide a brief summary of 50 characters or less. Summaries + of greater then 72 characters will be rejected by the gate. The first line of the commit message should provide an accurate description of the change, not just a reference to a bug or diff --git a/README.rst b/README.rst index 0e2a216f014..51f8fe11965 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ OpenStack Nova README OpenStack Nova provides a cloud computing fabric controller, supporting a wide variety of virtualization technologies, -including KVM, Xen, LXC, VMWare, and more. In addition to +including KVM, Xen, LXC, VMware, and more. In addition to its native API, it includes compatibility with the commonly encountered Amazon EC2 and S3 APIs. @@ -24,6 +24,11 @@ available online at: http://docs.openstack.org +For information about the different compute (hypervisor) drivers +supported by Nova, read this page on the wiki: + + https://wiki.openstack.org/wiki/HypervisorSupportMatrix + In the unfortunate event that bugs are discovered, they should be reported to the appropriate bug tracker. If you obtained the software from a 3rd party operating system vendor, it is @@ -50,9 +55,7 @@ developer focused documentation is available at: http://nova.openstack.org/ -Changes to OpenStack Nova should be submitted for review via -the Gerrit tool, following the workflow documented at: - - http://wiki.openstack.org/GerritWorkflow +For information on how to contribute to Nova, please see the +contents of the CONTRIBUTING.rst file. -- End of broadcast diff --git a/bin/api-paste.ini b/bin/api-paste.ini deleted file mode 120000 index bba6f5cc95f..00000000000 --- a/bin/api-paste.ini +++ /dev/null @@ -1 +0,0 @@ -../etc/nova/api-paste.ini \ No newline at end of file diff --git a/bin/nova-all b/bin/nova-all deleted file mode 100755 index 1d7b2dfaca0..00000000000 --- a/bin/nova-all +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack, LLC -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 all nova services. - -This script attempts to start all the nova services in one process. Each -service is started in its own greenthread. Please note that exceptions and -sys.exit() on the starting of a service are logged and the script will -continue attempting to launch the rest of the services. - -""" - -import eventlet -eventlet.monkey_patch(os=False) - -import os -import sys - - -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.objectstore import s3server -from nova.openstack.common import log as logging -from nova import service -from nova import utils -from nova.vnc import xvp_proxy - - -LOG = logging.getLogger('nova.all') - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - launcher = service.ProcessLauncher() - - # nova-api - for api in flags.FLAGS.enabled_apis: - try: - server = service.WSGIService(api) - launcher.launch_server(server, workers=server.workers or 1) - except (Exception, SystemExit): - LOG.exception(_('Failed to load %s') % '%s-api' % api) - - for mod in [s3server, xvp_proxy]: - try: - launcher.launch_server(mod.get_wsgi_server()) - except (Exception, SystemExit): - LOG.exception(_('Failed to load %s') % mod.__name__) - - for binary in ['nova-compute', 'nova-volume', - 'nova-network', 'nova-scheduler', 'nova-cert']: - try: - launcher.launch_server(service.Service.create(binary=binary)) - except (Exception, SystemExit): - LOG.exception(_('Failed to load %s'), binary) - launcher.wait() diff --git a/bin/nova-api b/bin/nova-api deleted file mode 100755 index f55eca719dd..00000000000 --- a/bin/nova-api +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 API. - -Starts both the EC2 and OpenStack APIs in separate greenthreads. - -""" - -import eventlet -eventlet.monkey_patch(os=False) - -import os -import sys - - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - launcher = service.ProcessLauncher() - for api in flags.FLAGS.enabled_apis: - server = service.WSGIService(api) - launcher.launch_server(server, workers=server.workers or 1) - launcher.wait() diff --git a/bin/nova-api-ec2 b/bin/nova-api-ec2 deleted file mode 100755 index 8e66ab87489..00000000000 --- a/bin/nova-api-ec2 +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 EC2 API.""" - -import eventlet -eventlet.monkey_patch(os=False) - -import os -import sys - - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - server = service.WSGIService('ec2') - service.serve(server, workers=server.workers) - service.wait() diff --git a/bin/nova-api-metadata b/bin/nova-api-metadata deleted file mode 100755 index d445a16a979..00000000000 --- a/bin/nova-api-metadata +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 Metadata API.""" - -import eventlet -eventlet.monkey_patch(os=False) - -import os -import sys - - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - server = service.WSGIService('metadata') - service.serve(server, workers=server.workers) - service.wait() diff --git a/bin/nova-api-os-compute b/bin/nova-api-os-compute deleted file mode 100755 index 529d5882125..00000000000 --- a/bin/nova-api-os-compute +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 OS API.""" - -import eventlet -eventlet.monkey_patch(os=False) - -import os -import sys - - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - server = service.WSGIService('osapi_compute') - service.serve(server, workers=server.workers) - service.wait() diff --git a/bin/nova-api-os-volume b/bin/nova-api-os-volume deleted file mode 100755 index 7c368fce931..00000000000 --- a/bin/nova-api-os-volume +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 OS API.""" - -import eventlet -eventlet.monkey_patch(os=False) - -import os -import sys - - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - server = service.WSGIService('osapi_volume') - service.serve(server, workers=server.workers) - service.wait() diff --git a/bin/nova-cert b/bin/nova-cert deleted file mode 100755 index 81189492a9a..00000000000 --- a/bin/nova-cert +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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 Cert.""" - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - utils.monkey_patch() - server = service.Service.create(binary='nova-cert') - service.serve(server) - service.wait() diff --git a/bin/nova-clear-rabbit-queues b/bin/nova-clear-rabbit-queues deleted file mode 100755 index 0cbf5ab196b..00000000000 --- a/bin/nova-clear-rabbit-queues +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2011 OpenStack, LLC. -# All Rights Reserved. -# -# 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. - -"""Admin/debug script to wipe rabbitMQ (AMQP) queues nova uses. - This can be used if you need to change durable options on queues, - or to wipe all messages in the queue system if things are in a - serious bad way. - -""" - -import datetime -import gettext -import os -import sys -import time - -# 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) - -gettext.install('nova', unicode=1) - - -from nova import context -from nova import exception -from nova import flags -from nova.openstack.common import cfg -from nova.openstack.common import log as logging -from nova.openstack.common import rpc - - -delete_exchange_opt = cfg.BoolOpt('delete_exchange', - default=False, - help='delete nova exchange too.') - -FLAGS = flags.FLAGS -FLAGS.register_cli_opt(delete_exchange_opt) - - -def delete_exchange(exch): - conn = rpc.create_connection() - x = conn.get_channel() - x.exchange_delete(exch) - - -def delete_queues(queues): - conn = rpc.create_connection() - x = conn.get_channel() - for q in queues: - x.queue_delete(q) - -if __name__ == '__main__': - args = flags.parse_args(sys.argv) - logging.setup("nova") - delete_queues(args[1:]) - if FLAGS.delete_exchange: - delete_exchange(FLAGS.control_exchange) diff --git a/bin/nova-compute b/bin/nova-compute deleted file mode 100755 index 0a8432b1e1c..00000000000 --- a/bin/nova-compute +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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 Compute.""" - -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.openstack.common import log as logging -from nova import service -from nova import utils - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup('nova') - utils.monkey_patch() - server = service.Service.create(binary='nova-compute') - service.serve(server) - service.wait() diff --git a/bin/nova-console b/bin/nova-console deleted file mode 100755 index 97b1529300f..00000000000 --- a/bin/nova-console +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2010 OpenStack, LLC. -# All Rights Reserved. -# -# 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 Console Proxy.""" - -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.openstack.common import log as logging -from nova import service - -if __name__ == '__main__': - flags.parse_args(sys.argv) - logging.setup("nova") - server = service.Service.create(binary='nova-console') - service.serve(server) - service.wait() diff --git a/bin/nova-consoleauth b/bin/nova-consoleauth deleted file mode 100755 index f8277daf63d..00000000000 --- a/bin/nova-consoleauth +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 OpenStack, LLC. -# All Rights Reserved. -# -# 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. - -"""VNC Console Proxy Server.""" - -import eventlet -eventlet.monkey_patch() - -import os -import sys - -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.consoleauth import manager -from nova import flags -from nova.openstack.common import log as logging -from nova import service - - -if __name__ == "__main__": - flags.parse_args(sys.argv) - logging.setup("nova") - - server = service.Service.create(binary='nova-consoleauth') - service.serve(server) - service.wait() diff --git a/bin/nova-dhcpbridge b/bin/nova-dhcpbridge deleted file mode 100755 index 0693ae27a44..00000000000 --- a/bin/nova-dhcpbridge +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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. - -""" -Handle lease database updates from DHCP servers. -""" - -import gettext -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) - -gettext.install('nova', unicode=1) - -from nova import context -from nova import db -from nova import flags -from nova.network import linux_net -from nova.openstack.common import importutils -from nova.openstack.common import log as logging -from nova.openstack.common import rpc -from nova import utils - -FLAGS = flags.FLAGS - -LOG = logging.getLogger('nova.dhcpbridge') - - -def add_lease(mac, ip_address): - """Set the IP that was assigned by the DHCP server.""" - if FLAGS.fake_rabbit: - LOG.debug(_("leasing ip")) - network_manager = importutils.import_object(FLAGS.network_manager) - network_manager.lease_fixed_ip(context.get_admin_context(), - ip_address) - else: - rpc.cast(context.get_admin_context(), - "%s.%s" % (FLAGS.network_topic, FLAGS.host), - {"method": "lease_fixed_ip", - "args": {"address": ip_address}}) - - -def old_lease(mac, ip_address): - """Called when an old lease is recognized.""" - # NOTE(vish): We assume we heard about this lease the first time. - # If not, we will get it the next time the lease is - # renewed. - pass - - -def del_lease(mac, ip_address): - """Called when a lease expires.""" - if FLAGS.fake_rabbit: - LOG.debug(_("releasing ip")) - network_manager = importutils.import_object(FLAGS.network_manager) - network_manager.release_fixed_ip(context.get_admin_context(), - ip_address) - else: - rpc.cast(context.get_admin_context(), - "%s.%s" % (FLAGS.network_topic, FLAGS.host), - {"method": "release_fixed_ip", - "args": {"address": ip_address}}) - - -def init_leases(network_id): - """Get the list of hosts for a network.""" - ctxt = context.get_admin_context() - network_ref = db.network_get(ctxt, network_id) - network_manager = importutils.import_object(FLAGS.network_manager) - return network_manager.get_dhcp_leases(ctxt, network_ref) - - -def main(): - """Parse environment and arguments and call the approproate action.""" - flagfile = os.environ.get('FLAGFILE', FLAGS.dhcpbridge_flagfile) - argv = flags.parse_args(sys.argv) - logging.setup("nova") - - if int(os.environ.get('TESTING', '0')): - from nova.tests import fake_flags - - action = argv[1] - if action in ['add', 'del', 'old']: - mac = argv[2] - ip = argv[3] - msg = (_("Called '%(action)s' for mac '%(mac)s' with ip '%(ip)s'") % - {"action": action, - "mac": mac, - "ip": ip}) - LOG.debug(msg) - globals()[action + '_lease'](mac, ip) - else: - try: - network_id = int(os.environ.get('NETWORK_ID')) - except TypeError: - LOG.error(_("Environment variable 'NETWORK_ID' must be set.")) - sys.exit(1) - - print init_leases(network_id) - - rpc.cleanup() - - -if __name__ == "__main__": - main() diff --git a/bin/nova-manage b/bin/nova-manage deleted file mode 100755 index 176273c7202..00000000000 --- a/bin/nova-manage +++ /dev/null @@ -1,1400 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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. - -# Interactive shell based on Django: -# -# Copyright (c) 2005, the Lawrence Journal-World -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of Django nor the names of its contributors may be -# used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -""" - CLI interface for nova management. -""" - -import ast -import errno -import gettext -import math -import netaddr -import optparse -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) - -gettext.install('nova', unicode=1) - -from nova.api.ec2 import ec2utils -from nova.compat import flagfile -from nova.compute import instance_types -from nova.compute import rpcapi as compute_rpcapi -from nova import context -from nova import db -from nova.db import migration -from nova import exception -from nova import flags -from nova.openstack.common import cfg -from nova.openstack.common import importutils -from nova.openstack.common import log as logging -from nova.openstack.common import rpc -from nova.openstack.common import timeutils -from nova import quota -from nova.scheduler import rpcapi as scheduler_rpcapi -from nova import utils -from nova import version - -FLAGS = flags.FLAGS -flags.DECLARE('flat_network_bridge', 'nova.network.manager') -flags.DECLARE('num_networks', 'nova.network.manager') -flags.DECLARE('multi_host', 'nova.network.manager') -flags.DECLARE('network_size', 'nova.network.manager') -flags.DECLARE('vlan_start', 'nova.network.manager') -flags.DECLARE('vpn_start', 'nova.network.manager') -flags.DECLARE('default_floating_pool', 'nova.network.manager') -flags.DECLARE('public_interface', 'nova.network.linux_net') - -QUOTAS = quota.QUOTAS - - -# Decorators for actions -def args(*args, **kwargs): - def _decorator(func): - func.__dict__.setdefault('options', []).insert(0, (args, kwargs)) - return func - return _decorator - - -def param2id(object_id): - """Helper function to convert various volume id types to internal id. - args: [object_id], e.g. 'vol-0000000a' or 'volume-0000000a' or '10' - """ - if '-' in object_id: - return ec2utils.ec2_vol_id_to_uuid(object_id) - else: - return object_id - - -class VpnCommands(object): - """Class for managing VPNs.""" - - @args('--project', dest="project_id", metavar='', - help='Project name') - @args('--ip', dest="ip", metavar='', help='IP Address') - @args('--port', dest="port", metavar='', help='Port') - def change(self, project_id, ip, port): - """Change the ip and port for a vpn. - - this will update all networks associated with a project - not sure if that's the desired behavior or not, patches accepted - - """ - # TODO(tr3buchet): perhaps this shouldn't update all networks - # associated with a project in the future - admin_context = context.get_admin_context() - networks = db.project_get_networks(admin_context, project_id) - for network in networks: - db.network_update(admin_context, - network['id'], - {'vpn_public_address': ip, - 'vpn_public_port': int(port)}) - - -class ShellCommands(object): - def bpython(self): - """Runs a bpython shell. - - Falls back to Ipython/python shell if unavailable""" - self.run('bpython') - - def ipython(self): - """Runs an Ipython shell. - - Falls back to Python shell if unavailable""" - self.run('ipython') - - def python(self): - """Runs a python shell. - - Falls back to Python shell if unavailable""" - self.run('python') - - @args('--shell', dest="shell", metavar='', - help='Python shell') - def run(self, shell=None): - """Runs a Python interactive interpreter.""" - if not shell: - shell = 'bpython' - - if shell == 'bpython': - try: - import bpython - bpython.embed() - except ImportError: - shell = 'ipython' - if shell == 'ipython': - try: - import IPython - # Explicitly pass an empty list as arguments, because - # otherwise IPython would use sys.argv from this script. - shell = IPython.Shell.IPShell(argv=[]) - shell.mainloop() - except ImportError: - shell = 'python' - - if shell == 'python': - import code - try: - # Try activating rlcompleter, because it's handy. - import readline - except ImportError: - pass - else: - # We don't have to wrap the following import in a 'try', - # because we already know 'readline' was imported successfully. - import rlcompleter - readline.parse_and_bind("tab:complete") - code.interact() - - @args('--path', dest='path', metavar='', help='Script path') - def script(self, path): - """Runs the script from the specifed path with flags set properly. - arguments: path""" - exec(compile(open(path).read(), path, 'exec'), locals(), globals()) - - -def _db_error(caught_exception): - print caught_exception - print _("The above error may show that the database has not " - "been created.\nPlease create a database using " - "'nova-manage db sync' before running this command.") - exit(1) - - -class ProjectCommands(object): - """Class for managing projects.""" - - def quota(self, project_id, key=None, value=None): - """Set or display quotas for project""" - ctxt = context.get_admin_context() - if key: - if value.lower() == 'unlimited': - value = -1 - try: - db.quota_update(ctxt, project_id, key, value) - except exception.ProjectQuotaNotFound: - db.quota_create(ctxt, project_id, key, value) - project_quota = QUOTAS.get_project_quotas(ctxt, project_id) - for key, value in project_quota.iteritems(): - if value['limit'] < 0 or value['limit'] is None: - value['limit'] = 'unlimited' - print '%s: %s' % (key, value['limit']) - - @args('--project', dest="project_id", metavar='', - help='Project name') - def scrub(self, project_id): - """Deletes data associated with project""" - admin_context = context.get_admin_context() - networks = db.project_get_networks(admin_context, project_id) - for network in networks: - db.network_disassociate(admin_context, network['id']) - groups = db.security_group_get_by_project(admin_context, project_id) - for group in groups: - db.security_group_destroy(admin_context, group['id']) - - -AccountCommands = ProjectCommands - - -class FixedIpCommands(object): - """Class for managing fixed ip.""" - - @args('--host', dest="host", metavar='', help='Host') - def list(self, host=None): - """Lists all fixed ips (optionally by host)""" - ctxt = context.get_admin_context() - - try: - if host is None: - fixed_ips = db.fixed_ip_get_all(ctxt) - else: - fixed_ips = db.fixed_ip_get_all_by_instance_host(ctxt, host) - except exception.NotFound as ex: - print "error: %s" % ex - sys.exit(2) - - instances = db.instance_get_all(context.get_admin_context()) - instances_by_uuid = {} - for instance in instances: - instances_by_uuid[instance['uuid']] = instance - - print "%-18s\t%-15s\t%-15s\t%s" % (_('network'), - _('IP address'), - _('hostname'), - _('host')) - - all_networks = {} - try: - # use network_get_all to retrieve all existing networks - # this is to ensure that IPs associated with deleted networks - # will not throw exceptions. - for network in db.network_get_all(context.get_admin_context()): - all_networks[network.id] = network - except exception.NoNetworksFound: - # do not have any networks, so even if there are IPs, these - # IPs should have been deleted ones, so return. - print _('No fixed IP found.') - return - - has_ip = False - for fixed_ip in fixed_ips: - hostname = None - host = None - mac_address = None - network = all_networks.get(fixed_ip['network_id']) - if network: - has_ip = True - if fixed_ip.get('instance_uuid'): - instance = instances_by_uuid.get(fixed_ip['instance_uuid']) - if instance: - hostname = instance['hostname'] - host = instance['host'] - else: - print _('WARNING: fixed ip %s allocated to missing' - ' instance') % str(fixed_ip['address']) - print "%-18s\t%-15s\t%-15s\t%s" % ( - network['cidr'], - fixed_ip['address'], - hostname, host) - - if not has_ip: - print _('No fixed IP found.') - - @args('--address', dest="address", metavar='', - help='IP address') - def reserve(self, address): - """Mark fixed ip as reserved - arguments: address""" - self._set_reserved(address, True) - - @args('--address', dest="address", metavar='', - help='IP address') - def unreserve(self, address): - """Mark fixed ip as free to use - arguments: address""" - self._set_reserved(address, False) - - def _set_reserved(self, address, reserved): - ctxt = context.get_admin_context() - - try: - fixed_ip = db.fixed_ip_get_by_address(ctxt, address) - if fixed_ip is None: - raise exception.NotFound('Could not find address') - db.fixed_ip_update(ctxt, fixed_ip['address'], - {'reserved': reserved}) - except exception.NotFound as ex: - print "error: %s" % ex - sys.exit(2) - - -class FloatingIpCommands(object): - """Class for managing floating ip.""" - - @staticmethod - def address_to_hosts(addresses): - """ - Iterate over hosts within an address range. - - If an explicit range specifier is missing, the parameter is - interpreted as a specific individual address. - """ - try: - return [netaddr.IPAddress(addresses)] - except ValueError: - net = netaddr.IPNetwork(addresses) - if net.size < 4: - reason = _("/%s should be specified as single address(es) " - "not in cidr format") % net.prefixlen - raise exception.InvalidInput(reason=reason) - else: - return net.iter_hosts() - - @args('--ip_range', dest="ip_range", metavar='', help='IP range') - @args('--pool', dest="pool", metavar='', help='Optional pool') - @args('--interface', dest="interface", metavar='', - help='Optional interface') - def create(self, ip_range, pool=None, interface=None): - """Creates floating ips for zone by range""" - admin_context = context.get_admin_context() - if not pool: - pool = FLAGS.default_floating_pool - if not interface: - interface = FLAGS.public_interface - - ips = ({'address': str(address), 'pool': pool, 'interface': interface} - for address in self.address_to_hosts(ip_range)) - try: - db.floating_ip_bulk_create(admin_context, ips) - except exception.FloatingIpExists as exc: - # NOTE(simplylizz): Maybe logging would be better here - # instead of printing, but logging isn't used here and I - # don't know why. - print('error: %s' % exc) - sys.exit(1) - - @args('--ip_range', dest="ip_range", metavar='', help='IP range') - def delete(self, ip_range): - """Deletes floating ips by range""" - admin_context = context.get_admin_context() - - ips = ({'address': str(address)} - for address in self.address_to_hosts(ip_range)) - db.floating_ip_bulk_destroy(admin_context, ips) - - @args('--host', dest="host", metavar='', help='Host') - def list(self, host=None): - """Lists all floating ips (optionally by host) - Note: if host is given, only active floating IPs are returned""" - ctxt = context.get_admin_context() - try: - if host is None: - floating_ips = db.floating_ip_get_all(ctxt) - else: - floating_ips = db.floating_ip_get_all_by_host(ctxt, host) - except exception.NoFloatingIpsDefined: - print _("No floating IP addresses have been defined.") - return - for floating_ip in floating_ips: - instance_uuid = None - if floating_ip['fixed_ip_id']: - fixed_ip = db.fixed_ip_get(ctxt, floating_ip['fixed_ip_id']) - instance_uuid = fixed_ip['instance_uuid'] - - print "%s\t%s\t%s\t%s\t%s" % (floating_ip['project_id'], - floating_ip['address'], - instance_uuid, - floating_ip['pool'], - floating_ip['interface']) - - -class NetworkCommands(object): - """Class for managing networks.""" - - @args('--label', dest="label", metavar='