diff --git a/rackclient/client.py b/rackclient/client.py index 83bed22..ad18302 100644 --- a/rackclient/client.py +++ b/rackclient/client.py @@ -15,7 +15,6 @@ import copy import json import logging import requests -from rackclient.openstack.common.gettextutils import _ from rackclient import exceptions from rackclient.openstack.common import importutils @@ -123,9 +122,9 @@ def get_client_class(version): try: client_path = version_map[str(version)] except (KeyError, ValueError): - msg = _("Invalid client version '%(version)s'. must be one of: " - "%(keys)s") % {'version': version, - 'keys': ', '.join(version_map.keys())} + msg = ("Invalid client version '%(version)s'. must be one of: " + "%(keys)s") % {'version': version, + 'keys': ', '.join(version_map.keys())} raise exceptions.UnsupportedVersion(msg) return importutils.import_class(client_path) diff --git a/rackclient/exceptions.py b/rackclient/exceptions.py index dc229f2..6b71d3b 100644 --- a/rackclient/exceptions.py +++ b/rackclient/exceptions.py @@ -11,6 +11,8 @@ # 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. + + class UnsupportedVersion(Exception): """Indicates that the user is trying to use an unsupported version of the API. @@ -107,7 +109,8 @@ def from_response(response, body, url, method=None): class BaseError(Exception): """ - The base exception class for all exceptions except for HTTPException based classes. + The base exception class for all exceptions except for HTTPException + based classes. """ pass diff --git a/rackclient/lib/__init__.py b/rackclient/lib/__init__.py index 3aa4e42..e1e84b0 100644 --- a/rackclient/lib/__init__.py +++ b/rackclient/lib/__init__.py @@ -1,107 +1,21 @@ -from rackclient import exceptions -from rackclient.client import Client - -import cPickle -import json -import logging +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. +import initializing import os -import pika -import requests - -LOG = logging.getLogger(__name__) - -META_URL = 'http://169.254.169.254/openstack/latest/meta_data.json' RACK_CTX = None - -def get_rack_context(proxy_port=8088, client_version="1", api_version="v1"): - global RACK_CTX - - if not RACK_CTX: - try: - resp = requests.get(META_URL) - metadata = json.loads(resp.text)["meta"] - proxy_url = 'http://%s:%d/%s' % (metadata["proxy_ip"], proxy_port, api_version) - client = Client(client_version, rack_url=proxy_url) - proxy_info = client.proxy.get(metadata["gid"]) - - RACK_CTX = type('', (object,), metadata) - RACK_CTX.ppid = getattr(RACK_CTX, "ppid", "") - RACK_CTX.client = client - RACK_CTX.fs_endpoint = proxy_info.fs_endpoint - RACK_CTX.ipc_endpoint = proxy_info.ipc_endpoint - RACK_CTX.shm_endpoint = proxy_info.shm_endpoint - - try: - # Check if this process is not recognized by RACK. - RACK_CTX.client.processes.get(RACK_CTX.gid, RACK_CTX.pid) - except exceptions.NotFound: - msg = "This process is not recognized by RACK" - raise exceptions.InvalidProcessError(msg) - - if RACK_CTX.ppid: - LOG.debug("Messaging: send message to %s", RACK_CTX.ppid) - msg = _Messaging(RACK_CTX) - msg.send_msg(RACK_CTX.ppid) - while True: - receive_msg = msg.receive_msg(getattr(RACK_CTX, "msg_limit_time", 180)) - if receive_msg and RACK_CTX.ppid == receive_msg.get("pid"): - LOG.debug("Messaging: receive message from %s", receive_msg.get("pid")) - break - - except Exception as e: - msg = "Failed to initialize the process: %s." % e.message - raise exceptions.ProcessInitError(msg) - - return RACK_CTX - - -class _Messaging(object): - - def __init__(self, ctx): - self.ctx = ctx - connection_param = pika.ConnectionParameters(self.ctx.proxy_ip) - if self.ctx.ipc_endpoint: - connection_param = pika.ConnectionParameters(self.ctx.ipc_endpoint) - self.connection = pika.BlockingConnection(connection_param) - self.channel = self.connection.channel() - self.channel.exchange_declare(exchange=ctx.gid, type='topic') - self.channel.queue_declare(queue=ctx.pid) - self.channel.queue_bind(exchange=ctx.gid, queue=ctx.pid, routing_key=ctx.gid + '.' + ctx.pid) - - - def receive_msg(self, timeout_limit=180): - queue_name = self.ctx.pid - self.channel = self.connection.channel() - receive = self.Receive() - self.connection.add_timeout(deadline=int(timeout_limit), callback_method=receive.time_out) - self.channel.basic_consume(receive.get_msg, queue=queue_name, no_ack=False) - receive.channel = self.channel - self.channel.start_consuming() - return receive.message - - - class Receive(object): - - def __init__(self): - self.channel = None - self.message = None - - def get_msg(self, ch, method, properties, body): - self.message = cPickle.loads(body) - ch.basic_ack(delivery_tag=method.delivery_tag) - ch.stop_consuming() - - def time_out(self): - self.channel.stop_consuming() - - - def send_msg(self, target): - routing_key = self.ctx.gid + '.' + target - send_dict = {'pid': self.ctx.pid} - send_msg = cPickle.dumps(send_dict) - self.channel.basic_publish(exchange=self.ctx.gid, routing_key=routing_key, body=send_msg) - if not os.environ.get("RACK_IS_TEST"): - get_rack_context() + if not RACK_CTX: + RACK_CTX = initializing.get_rack_context() diff --git a/rackclient/lib/initializing.py b/rackclient/lib/initializing.py new file mode 100644 index 0000000..cbf1286 --- /dev/null +++ b/rackclient/lib/initializing.py @@ -0,0 +1,126 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. +import cPickle +import json +import logging +import pika +import requests + +from rackclient import exceptions +from rackclient.client import Client + + +LOG = logging.getLogger(__name__) +LOG.setLevel(logging.DEBUG) + +META_URL = 'http://169.254.169.254/openstack/latest/meta_data.json' + + +def get_rack_context(proxy_port=8088, client_version="1", api_version="v1"): + + try: + resp = requests.get(META_URL) + metadata = json.loads(resp.text)["meta"] + proxy_url = 'http://%s:%d/%s' % ( + metadata["proxy_ip"], proxy_port, api_version) + client = Client(client_version, rack_url=proxy_url) + proxy_info = client.proxy.get(metadata["gid"]) + + rack_ctx = type('', (object,), metadata) + rack_ctx.ppid = getattr(rack_ctx, "ppid", "") + rack_ctx.client = client + rack_ctx.fs_endpoint = proxy_info.fs_endpoint + rack_ctx.ipc_endpoint = proxy_info.ipc_endpoint + rack_ctx.shm_endpoint = proxy_info.shm_endpoint + + try: + # Check if this process is not recognized by RACK. + rack_ctx.client.processes.get(rack_ctx.gid, rack_ctx.pid) + except exceptions.NotFound: + msg = "This process is not recognized by RACK" + raise exceptions.InvalidProcessError(msg) + + if rack_ctx.ppid: + LOG.debug("Messaging: send message to %s", rack_ctx.ppid) + msg = _Messaging(rack_ctx) + msg.send_msg(rack_ctx.ppid) + while True: + receive_msg = msg.receive_msg( + getattr(rack_ctx, "msg_limit_time", 180)) + if receive_msg and rack_ctx.ppid == receive_msg.get("pid"): + LOG.debug( + "Messaging: receive message from %s", + receive_msg.get("pid")) + break + + except Exception as e: + msg = "Failed to initialize the process: %s." % e.message + raise exceptions.ProcessInitError(msg) + + return rack_ctx + + +class _Messaging(object): + + def __init__(self, ctx): + self.ctx = ctx + connection_param = pika.ConnectionParameters(self.ctx.proxy_ip) + if self.ctx.ipc_endpoint: + connection_param = pika.ConnectionParameters(self.ctx.ipc_endpoint) + self.connection = pika.BlockingConnection(connection_param) + self.channel = self.connection.channel() + self.channel.exchange_declare(exchange=ctx.gid, type='topic') + self.channel.queue_declare(queue=ctx.pid) + self.channel.queue_bind( + exchange=ctx.gid, + queue=ctx.pid, + routing_key=ctx.gid + '.' + ctx.pid) + + def receive_msg(self, timeout_limit=180): + queue_name = self.ctx.pid + self.channel = self.connection.channel() + receive = self.Receive() + self.connection.add_timeout( + deadline=int(timeout_limit), + callback_method=receive.time_out) + self.channel.basic_consume( + receive.get_msg, + queue=queue_name, + no_ack=False) + receive.channel = self.channel + self.channel.start_consuming() + return receive.message + + def send_msg(self, target): + routing_key = self.ctx.gid + '.' + target + send_dict = {'pid': self.ctx.pid} + send_msg = cPickle.dumps(send_dict) + self.channel.basic_publish( + exchange=self.ctx.gid, + routing_key=routing_key, + body=send_msg) + + class Receive(object): + + def __init__(self): + self.channel = None + self.message = None + + def get_msg(self, ch, method, properties, body): + self.message = cPickle.loads(body) + ch.basic_ack(delivery_tag=method.delivery_tag) + ch.stop_consuming() + + def time_out(self): + self.channel.stop_consuming() diff --git a/rackclient/lib/syscall/default/file.py b/rackclient/lib/syscall/default/file.py index 563745f..f7dcb01 100644 --- a/rackclient/lib/syscall/default/file.py +++ b/rackclient/lib/syscall/default/file.py @@ -1,3 +1,16 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. from rackclient.lib import RACK_CTX from rackclient import exceptions from swiftclient import client as swift_client @@ -14,7 +27,6 @@ SWIFT_PORT = 8080 def _get_swift_client(): - if RACK_CTX.fs_endpoint: try: d = json.loads(RACK_CTX.fs_endpoint) @@ -90,7 +102,7 @@ class File(object): try: _, contents = swift.get_object(self.get_directory(), - self.get_name(), chunk_size) + self.get_name(), chunk_size) if chunk_size: for c in contents: self.file.write(c) @@ -140,4 +152,4 @@ class File(object): return getattr(self.file, name) else: raise AttributeError("%s instance has no attribute '%s'", - self.__class__.__name__, name) \ No newline at end of file + self.__class__.__name__, name) diff --git a/rackclient/lib/syscall/default/messaging.py b/rackclient/lib/syscall/default/messaging.py index ee6d11d..f935f80 100644 --- a/rackclient/lib/syscall/default/messaging.py +++ b/rackclient/lib/syscall/default/messaging.py @@ -1,3 +1,16 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. from rackclient.lib import RACK_CTX from rackclient import exceptions diff --git a/rackclient/lib/syscall/default/pipe.py b/rackclient/lib/syscall/default/pipe.py index ec5a932..7c4790c 100644 --- a/rackclient/lib/syscall/default/pipe.py +++ b/rackclient/lib/syscall/default/pipe.py @@ -1,3 +1,16 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. from datetime import datetime from rackclient.lib import RACK_CTX from rackclient import exceptions @@ -47,8 +60,10 @@ class Pipe: self.name = self.r.get(parent_pipe[0]) else: self.name = RACK_CTX.pid - read_state = self.r.hget(read_state_key(self.name), RACK_CTX.pid) or now - write_state = self.r.hget(write_state_key(self.name), RACK_CTX.pid) or now + read_state = \ + self.r.hget(read_state_key(self.name), RACK_CTX.pid) or now + write_state = \ + self.r.hget(write_state_key(self.name), RACK_CTX.pid) or now if read is not None: if read: read_state = now @@ -125,7 +140,7 @@ class Pipe: self.r.delete(*tuple(keys)) @classmethod - def flush_by_pid(self, pid, host=None): + def flush_by_pid(cls, pid, host=None): if not host: host = RACK_CTX.proxy_ip diff --git a/rackclient/lib/syscall/default/shm.py b/rackclient/lib/syscall/default/shm.py index 2c1149f..15994ad 100644 --- a/rackclient/lib/syscall/default/shm.py +++ b/rackclient/lib/syscall/default/shm.py @@ -1,15 +1,28 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. import logging import redis from rackclient.lib import RACK_CTX - LOG = logging.getLogger(__name__) FIFO = 3 PORT = 6379 + def get_host(): return RACK_CTX.proxy_ip @@ -39,4 +52,3 @@ class Shm(object): def delete(self, key): return self.r.delete(key) - diff --git a/rackclient/lib/syscall/default/signal.py b/rackclient/lib/syscall/default/signal.py index da50583..3c3f796 100644 --- a/rackclient/lib/syscall/default/signal.py +++ b/rackclient/lib/syscall/default/signal.py @@ -1,3 +1,16 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. import logging import websocket @@ -46,7 +59,8 @@ class SignalManager(object): LOG.debug("Websocket connection %s closed" % ws.header[0]) def send(self, target_id, message): - ws = websocket.create_connection(self.url + '/send', header=['PID: ' + target_id]) + ws = websocket.create_connection(self.url + '/send', + header=['PID: ' + target_id]) LOG.debug("Send a message: %s" % message) ws.send(message) ws.close() diff --git a/rackclient/lib/syscall/default/syscall.py b/rackclient/lib/syscall/default/syscall.py index ad9f3da..5dec003 100644 --- a/rackclient/lib/syscall/default/syscall.py +++ b/rackclient/lib/syscall/default/syscall.py @@ -1,3 +1,16 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. import logging import Queue import threading @@ -42,25 +55,6 @@ def fork(opt_list, timeout_limit=180): return return_process_list -def kill(pid): - RACK_CTX.client.processes.delete(RACK_CTX.gid, pid) - -def pipe(name=None): - p = rackpipe.Pipe(name) - return p - -def pipe_reader(name=None): - p = rackpipe.Pipe(name) - p.close_writer() - return p - -def pipe_writer(name=None): - p = rackpipe.Pipe(name) - p.close_reader() - return p - -def fopen(file_path, mode="r"): - return rackfile.File(file_path, mode) def _bulk_fork(pid, args_list): LOG.debug("start bulk_fork") @@ -69,8 +63,8 @@ def _bulk_fork(pid, args_list): def _fork(pid, **kwargs): try: child = RACK_CTX.client.processes.create(gid=RACK_CTX.gid, - ppid=pid, - **kwargs) + ppid=pid, + **kwargs) q.put(child) except Exception as e: attr = dict(args=kwargs, error=e) @@ -136,4 +130,17 @@ def _check_connection(pid, process_list, timeout): msg = "No child process is active." raise Exception(msg) - return actives, inactives \ No newline at end of file + return actives, inactives + + +def kill(pid): + RACK_CTX.client.processes.delete(RACK_CTX.gid, pid) + + +def pipe(name=None): + p = rackpipe.Pipe(name) + return p + + +def fopen(file_path, mode="r"): + return rackfile.File(file_path, mode) diff --git a/rackclient/shell.py b/rackclient/shell.py index 14bb9b2..11caf36 100644 --- a/rackclient/shell.py +++ b/rackclient/shell.py @@ -1,3 +1,16 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. import logging import os import sys @@ -8,7 +21,7 @@ import requests from rackclient import exceptions -VERSION='1' +VERSION = '1' class RackShell(App): @@ -25,7 +38,7 @@ class RackShell(App): def build_option_parser(self, description, version, argparse_kwargs=None): parser = super(RackShell, self).build_option_parser( - description, version, argparse_kwargs) + description, version, argparse_kwargs) parser.add_argument( '--rack-api-version', @@ -90,4 +103,3 @@ def main(argv=sys.argv[1:]): if __name__ == '__main__': sys.exit(main(sys.argv[1:])) - diff --git a/rackclient/tests/_test_process_context.py b/rackclient/tests/_test_process_context.py deleted file mode 100644 index 277223d..0000000 --- a/rackclient/tests/_test_process_context.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. -# -# 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. -from mock import patch -import requests -from rackclient import process_context as pctxt -from rackclient.tests import utils -from rackclient.v1.proxy import ProxyManager, Proxy -from rackclient import exceptions - - -class ProcessContextTest(utils.TestCase): - - def setUp(self): - super(ProcessContextTest, self).setUp() - - patcher = patch('requests.get') - self.addCleanup(patcher.stop) - self.mock_request = patcher.start() - self.mock_request.return_value = requests.Response() - self.mock_request.return_value._content = \ - ('{"meta": {"gid": "11111111", ' - '"pid": "22222222", "ppid": "33333333", ' - '"proxy_ip": "10.0.0.2", "opt1": "value1", ' - '"opt2": "value2"}}') - - @patch.object(ProxyManager, 'get') - def test_init(self, mock_proxy_get): - proxy = { - 'fs_endpoint': 'fs_endpoint', - 'shm_endpoint': 'shm_endpoint', - 'ipc_endpoint': 'ipc_endpoint' - } - mock_proxy_get.return_value = Proxy(None, proxy) - - pctxt.init() - d = pctxt.PCTXT.__dict__ - d.pop('client') - - expected = { - 'ipc_endpoint': 'ipc_endpoint', - 'fs_endpoint': 'fs_endpoint', - 'proxy_url': 'http://10.0.0.2:8088/v1', - 'pid': '22222222', - 'gid': '11111111', - 'proxy_ip': '10.0.0.2', - 'shm_endpoint': 'shm_endpoint', - 'ppid': '33333333', - 'opt1': 'value1', - 'opt2': 'value2' - } - self.assertEqual(expected, d) - mock_proxy_get.assert_called_with('11111111') - - def test_init_metadata_error(self): - self.mock_request.side_effect = Exception() - self.assertRaises(exceptions.MetadataAccessError, pctxt.init) diff --git a/rackclient/tests/fakes.py b/rackclient/tests/fakes.py index 2002118..7bc7012 100644 --- a/rackclient/tests/fakes.py +++ b/rackclient/tests/fakes.py @@ -11,6 +11,8 @@ # 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. + + class FakeClient(object): def assert_called(self, method, url, body=None, pos=-1): diff --git a/rackclient/tests/v1/syscall/__init__.py b/rackclient/tests/lib/__init__.py similarity index 100% rename from rackclient/tests/v1/syscall/__init__.py rename to rackclient/tests/lib/__init__.py diff --git a/rackclient/tests/v1/syscall/default/__init__.py b/rackclient/tests/lib/syscall/__init__.py similarity index 100% rename from rackclient/tests/v1/syscall/default/__init__.py rename to rackclient/tests/lib/syscall/__init__.py diff --git a/rackclient/tests/lib/syscall/default/__init__.py b/rackclient/tests/lib/syscall/default/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rackclient/tests/v1/syscall/default/test_file.py b/rackclient/tests/lib/syscall/default/test_file.py similarity index 100% rename from rackclient/tests/v1/syscall/default/test_file.py rename to rackclient/tests/lib/syscall/default/test_file.py diff --git a/rackclient/tests/v1/syscall/default/test_messaging.py b/rackclient/tests/lib/syscall/default/test_messaging.py similarity index 80% rename from rackclient/tests/v1/syscall/default/test_messaging.py rename to rackclient/tests/lib/syscall/default/test_messaging.py index 9b04006..e6ab3d0 100644 --- a/rackclient/tests/v1/syscall/default/test_messaging.py +++ b/rackclient/tests/lib/syscall/default/test_messaging.py @@ -32,13 +32,16 @@ class MessagingTest(utils.LibTestCase): self.mock_connection = Mock() self.mock_channel = Mock() self.mock_receive = Mock(spec=rack_ipc.Messaging.Receive) - self.patch_pika_blocking = patch('pika.BlockingConnection', - autospec=True) - self.addCleanup(self.patch_pika_blocking.stop) + self.patch_pika_blocking = patch('pika.BlockingConnection', autospec=True) + # self.addCleanup(self.patch_pika_blocking.stop) self.mock_pika_blocking = self.patch_pika_blocking.start() self.mock_pika_blocking.return_value = self.mock_connection self.mock_connection.channel.return_value = self.mock_channel + def tearDown(self): + super(MessagingTest, self).tearDown() + self.patch_pika_blocking.stop() + def test_declare_queue(self): queue_name = 'test_queue_name' msg = rack_ipc.Messaging() @@ -176,39 +179,21 @@ class MessagingTest(utils.LibTestCase): receive.time_out() self.mock_channel.stop_consuming.assert_called_with() - #@patch('rackclient.v1.syscall.default.messaging.Messaging', - # autospec=True) - # def test_init(self, msg): - # rack_ipc.init() - # msg.assert_called_with() - # - # @patch('rackclient.v1.syscall.default.messaging.Messaging', - # autospec=True) - # def test_init_child(self, msg): - # self.mock_RACK_CTX.ppid = 'PPID' - # receive_msg = {'pid': self.mock_RACK_CTX.ppid} - # mock_messaging = Mock() - # msg.return_value = mock_messaging - # mock_messaging.receive_msg.return_value = receive_msg - # rack_ipc.init() - # mock_messaging.send_msg.asset_called_with(self.mock_RACK_CTX.ppid) - # mock_messaging.receive_msg.assert_called_onece_with() + def test_create_connection(self): + p = patch('pika.ConnectionParameters', autospec=True) + self.addCleanup(p.stop) + mock_pika_connection_param = p.start() + rack_ipc.Messaging() + mock_pika_connection_param.assert_called_with(self.mock_RACK_CTX.proxy_ip) - # @patch('pika.ConnectionParameters', autospec=True) - # def test_create_connection(self, mock_pika_connection_param): - # rack_ipc._create_connection() - # mock_pika_connection_param.assert_called_with(self.mock_RACK_CTX.proxy_ip) - # - # @patch('pika.ConnectionParameters', autospec=True) - # def test_create_connection_ipc_endpoint(self, mock_pika_connection_param): - # ipc_ip = 'ipc_ip' - # self.mock_RACK_CTX.ipc_endpoint = ipc_ip - # - # rack_ipc._create_connection() - # mock_pika_connection_param.assert_called_with(ipc_ip) - # - # def test_create_connection_amqp_connection_error(self): - # self.mock_pika_blocking.side_effect = pika.\ - # exceptions.AMQPConnectionError() - # self.assertRaises(exceptions.AMQPConnectionError, - # rack_ipc._create_connection) \ No newline at end of file + @patch('pika.ConnectionParameters', autospec=True) + def test_create_connection_ipc_endpoint(self, mock_pika_connection_param): + ipc_ip = 'ipc_ip' + self.mock_RACK_CTX.ipc_endpoint = ipc_ip + rack_ipc.Messaging() + mock_pika_connection_param.assert_called_with(ipc_ip) + + def test_create_connection_amqp_connection_error(self): + self.mock_pika_blocking.side_effect = pika.\ + exceptions.AMQPConnectionError() + self.assertRaises(exceptions.AMQPConnectionError, rack_ipc.Messaging) \ No newline at end of file diff --git a/rackclient/tests/v1/syscall/default/test_pipe.py b/rackclient/tests/lib/syscall/default/test_pipe.py similarity index 100% rename from rackclient/tests/v1/syscall/default/test_pipe.py rename to rackclient/tests/lib/syscall/default/test_pipe.py diff --git a/rackclient/tests/v1/syscall/default/test_shm.py b/rackclient/tests/lib/syscall/default/test_shm.py similarity index 100% rename from rackclient/tests/v1/syscall/default/test_shm.py rename to rackclient/tests/lib/syscall/default/test_shm.py diff --git a/rackclient/tests/v1/syscall/default/test_signal.py b/rackclient/tests/lib/syscall/default/test_signal.py similarity index 97% rename from rackclient/tests/v1/syscall/default/test_signal.py rename to rackclient/tests/lib/syscall/default/test_signal.py index 85b07b8..4c0b160 100644 --- a/rackclient/tests/v1/syscall/default/test_signal.py +++ b/rackclient/tests/lib/syscall/default/test_signal.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import copy +import logging from mock import patch, Mock from rackclient.tests import utils @@ -25,6 +26,7 @@ class SignalTest(utils.LibTestCase): def setUp(self): super(SignalTest, self).setUp() + logging.basicConfig(level=logging.ERROR) @patch('websocket.WebSocketApp') def test_receive(self, mock_websocket_websocketapp): diff --git a/rackclient/tests/v1/syscall/default/test_syscall.py b/rackclient/tests/lib/syscall/default/test_syscall.py similarity index 100% rename from rackclient/tests/v1/syscall/default/test_syscall.py rename to rackclient/tests/lib/syscall/default/test_syscall.py diff --git a/rackclient/tests/lib/test_initializing.py b/rackclient/tests/lib/test_initializing.py new file mode 100644 index 0000000..04d79c1 --- /dev/null +++ b/rackclient/tests/lib/test_initializing.py @@ -0,0 +1,215 @@ +# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. +# +# 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. +import cPickle +import json +import logging + +from mock import * +from rackclient import exceptions +from rackclient.tests import utils +from rackclient.lib import initializing + + +LOG = logging.getLogger(__name__) +LOG.setLevel(logging.WARN) + + +class InitializingTest(utils.TestCase): + + def setUp(self): + super(InitializingTest, self).setUp() + p = patch("requests.get") + self.addCleanup(p.stop) + mock_request = p.start() + mock_resp = Mock() + mock_resp.text= json.dumps(dict(meta=dict( + proxy_ip="10.0.0.2",gid="gid", pid="pid", ppid="ppid"))) + mock_request.return_value = mock_resp + + def test_get_rack_context(self): + p = patch("rackclient.lib.initializing.Client") + self.addCleanup(p.stop) + mock_client = p.start() + mock_client = mock_client.return_value + + def proxy_info(args): + info = type('', (object,), {}) + info.ipc_endpoint = None + info.fs_endpoint = None + info.shm_endpoint = None + return info + + mock_client.proxy = Mock() + mock_client_processes = Mock() + mock_client.proxy.get.side_effect = proxy_info + p2 = patch("rackclient.lib.initializing._Messaging") + self.addCleanup(p2.stop) + mock_messaging = p2.start() + mock_messaging = mock_messaging.return_value + mock_messaging.receive_msg.return_value=dict(pid="ppid") + actual_context = initializing.get_rack_context() + + expect_context = type('', (object,), dict( + proxy_ip="10.0.0.2", + gid="gid", pid="pid", + ppid="ppid", + ipc_endpoint=None, + fs_endpoint=None, + shm_endpoint=None, + client=mock_client)) + + self.assertEquals(expect_context.pid, actual_context.pid) + self.assertEquals(expect_context.ppid, actual_context.ppid) + self.assertEquals(expect_context.proxy_ip, actual_context.proxy_ip) + self.assertEquals(expect_context.ipc_endpoint, actual_context.ipc_endpoint) + self.assertEquals(expect_context.fs_endpoint, actual_context.fs_endpoint) + self.assertEquals(expect_context.shm_endpoint, actual_context.shm_endpoint) + + def test_get_rack_cotext_ProcessInitError_due_to_proxy(self): + self.p = patch("rackclient.lib.initializing.Client") + self.addCleanup(self.p.stop) + mock_client = self.p.start() + mock_client = mock_client.return_value + mock_client.proxy = Mock() + mock_client_processes = Mock() + mock_client.proxy.get.side_effect = Exception() + self.assertRaises(Exception, initializing.get_rack_context) + + def test_get_rack_cotext_ProcessInitError_doe_to_processes(self): + self.p = patch("rackclient.lib.initializing.Client") + self.addCleanup(self.p.stop) + mock_client = self.p.start() + mock_client = mock_client.return_value + mock_client.proxy = Mock() + mock_client_processes = Mock() + mock_client.processes.get.side_effect = exceptions.NotFound("") + self.assertRaises(Exception, initializing.get_rack_context) + + @patch("rackclient.lib.initializing._Messaging.Receive") + def test_messaging_receive_msg(self, mock_receive): + self.mock_connection = Mock() + self.mock_channel = Mock() + self.patch_pika_blocking = patch('pika.BlockingConnection', autospec=True) + self.addCleanup(self.patch_pika_blocking.stop) + self.mock_pika_blocking = self.patch_pika_blocking.start() + self.mock_pika_blocking.return_value = self.mock_connection + self.mock_connection.channel.return_value = self.mock_channel + + context = type('', (object,), dict( + proxy_ip="10.0.0.2", + gid="gid", pid="pid", + ppid="ppid", + ipc_endpoint=None, + fs_endpoint=None, + shm_endpoint=None)) + + timeout_limit = 123 + msg = initializing._Messaging(context) + message = msg.receive_msg(timeout_limit=timeout_limit) + + self.mock_connection.add_timeout.\ + assert_called_with(deadline=int(timeout_limit), + callback_method=mock_receive().time_out) + self.mock_channel.\ + basic_consume.assert_called_with(mock_receive().get_msg, + queue="pid", + no_ack=False) + self.mock_channel.start_consuming.assert_called_with() + self.assertEqual(message, mock_receive().message) + + + def test_messaging_send_msg(self): + self.mock_connection = Mock() + self.mock_channel = Mock() + self.patch_pika_blocking = patch('pika.BlockingConnection', autospec=True) + self.addCleanup(self.patch_pika_blocking.stop) + self.mock_pika_blocking = self.patch_pika_blocking.start() + self.mock_pika_blocking.return_value = self.mock_connection + self.mock_connection.channel.return_value = self.mock_channel + + context = type('', (object,), dict( + proxy_ip="10.0.0.2", + gid="gid", pid="pid", + ppid="ppid", + ipc_endpoint=None, + fs_endpoint=None, + shm_endpoint=None)) + + send_msg = 'test_msg' + target = 'test_pid' + msg = initializing._Messaging(context) + msg.send_msg(target) + routing_key = context.gid + '.' + target + send_dict = {'pid': context.pid} + send_msg = cPickle.dumps(send_dict) + self.mock_channel.\ + basic_publish.assert_called_with(exchange=context.gid, + routing_key=routing_key, + body=send_msg) + + def test_receive_get_msg(self): + self.mock_connection = Mock() + self.mock_channel = Mock() + self.patch_pika_blocking = patch('pika.BlockingConnection', autospec=True) + self.addCleanup(self.patch_pika_blocking.stop) + self.mock_pika_blocking = self.patch_pika_blocking.start() + self.mock_pika_blocking.return_value = self.mock_connection + self.mock_connection.channel.return_value = self.mock_channel + + ch = Mock() + method = Mock() + properties = Mock() + receive_msg = 'receive_msg' + body = cPickle.dumps(receive_msg) + ch_object = {'delivery_tag': 'delivery_tag'} + method.configure_mock(**ch_object) + + context = type('', (object,), dict( + proxy_ip="10.0.0.2", + gid="gid", pid="pid", + ppid="ppid", + ipc_endpoint=None, + fs_endpoint=None, + shm_endpoint=None)) + + msg = initializing._Messaging(context) + receive = msg.Receive() + receive.get_msg(ch, method, properties, body) + + ch.basic_ack.assert_called_with(delivery_tag=ch_object['delivery_tag']) + ch.stop_consuming.assert_call_with() + self.assertEqual(receive.message, receive_msg) + + def test_receive_timeout(self): + self.mock_connection = Mock() + self.mock_channel = Mock() + self.patch_pika_blocking = patch('pika.BlockingConnection', autospec=True) + self.addCleanup(self.patch_pika_blocking.stop) + self.mock_pika_blocking = self.patch_pika_blocking.start() + self.mock_pika_blocking.return_value = self.mock_connection + self.mock_connection.channel.return_value = self.mock_channel + + context = type('', (object,), dict( + proxy_ip="10.0.0.2", + gid="gid", pid="pid", + ppid="ppid", + ipc_endpoint="data", + fs_endpoint=None, + shm_endpoint=None)) + + msg = initializing._Messaging(context) + receive = msg.Receive() + receive.channel = self.mock_channel + receive.time_out() + self.mock_channel.stop_consuming.assert_called_with() diff --git a/rackclient/tests/test_client.py b/rackclient/tests/test_client.py index cf157e7..1ac612e 100644 --- a/rackclient/tests/test_client.py +++ b/rackclient/tests/test_client.py @@ -19,6 +19,7 @@ import requests from rackclient import client from rackclient.tests import utils + class ClientTest(utils.TestCase): def test_log_req(self): diff --git a/rackclient/tests/utils.py b/rackclient/tests/utils.py index 0f2b1f2..22d3c05 100644 --- a/rackclient/tests/utils.py +++ b/rackclient/tests/utils.py @@ -18,61 +18,30 @@ from rackclient import client from mock import * -# class PContextFixture(fixture.Fixture): -# -# def setUp(self): -# super(PContextFixture, self).setUp() -# self.attrs = dir(PCTXT) -# self.addCleanup(self.cleanup_pctxt) -# -# PCTXT.gid = 'gid' -# PCTXT.pid = 'pid' -# PCTXT.ppid = None -# PCTXT.proxy_ip = '10.0.0.2' -# PCTXT.proxy_url = 'http://10.0.0.2:8088/v1' -# PCTXT.fs_endpoint = None -# PCTXT.shm_endpoint = None -# PCTXT.ipc_endpoint = None -# PCTXT.client = client.Client('1', rack_url=PCTXT.proxy_url) -# -# def cleanup_pctxt(self): -# attrs = dir(PCTXT) -# for attr in attrs: -# if attr not in self.attrs: delattr(PCTXT, attr) - - class TestCase(testtools.TestCase): def setUp(self): super(TestCase, self).setUp() - # if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or - # os.environ.get('OS_STDOUT_CAPTURE') == '1'): - # stdout = self.useFixture(fixtures.StringStream('stdout')).stream - # self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - # if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or - # os.environ.get('OS_STDERR_CAPTURE') == '1'): - # stderr = self.useFixture(fixtures.StringStream('stderr')).stream - # self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - -# self.useFixture(PContextFixture()) class LibTestCase(testtools.TestCase): def setUp(self): super(LibTestCase, self).setUp() - patcher = patch("rackclient.lib." + self.target_context() + ".RACK_CTX") + patcher = patch( + "rackclient.lib." + self.target_context() + ".RACK_CTX") self.addCleanup(patcher.stop) self.mock_RACK_CTX = patcher.start() self._init_context() def _init_context(self): - self.mock_RACK_CTX.gid="gid" - self.mock_RACK_CTX.pid="pid" - self.mock_RACK_CTX.ppid=None - self.mock_RACK_CTX.proxy_ip="10.0.0.2" + self.mock_RACK_CTX.gid = "gid" + self.mock_RACK_CTX.pid = "pid" + self.mock_RACK_CTX.ppid = None + self.mock_RACK_CTX.proxy_ip = "10.0.0.2" self.mock_RACK_CTX.proxy_url = 'http://10.0.0.2:8088/v1' - self.mock_RACK_CTX.client = client.Client('1', rack_url=self.mock_RACK_CTX.proxy_url) + self.mock_RACK_CTX.client = \ + client.Client('1', rack_url=self.mock_RACK_CTX.proxy_url) self.mock_RACK_CTX.fs_endpoint = None self.mock_RACK_CTX.ipc_endpoint = None self.mock_RACK_CTX.shm_endpoint = None @@ -80,6 +49,7 @@ class LibTestCase(testtools.TestCase): def target_context(self): pass + class TestResponse(requests.Response): """ Class used to wrap requests.Response and provide some diff --git a/rackclient/v1/command/__init__.py b/rackclient/v1/command/__init__.py index f7689ed..e69de29 100644 --- a/rackclient/v1/command/__init__.py +++ b/rackclient/v1/command/__init__.py @@ -1,13 +0,0 @@ -# Copyright (c) 2014 ITOCHU Techno-Solutions Corporation. -# -# 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. diff --git a/rackclient/v1/command/groups.py b/rackclient/v1/command/groups.py index ddcc6a8..20f6c7e 100644 --- a/rackclient/v1/command/groups.py +++ b/rackclient/v1/command/groups.py @@ -147,7 +147,9 @@ class CreateGroup(ShowOne): return parser def take_action(self, parsed_args): - group = self.client.groups.create(parsed_args.name, parsed_args.description) + group = self.client.groups.create( + parsed_args.name, + parsed_args.description) return _make_print_data( group.gid, group.name, @@ -184,8 +186,8 @@ class UpdateGroup(ShowOne): def take_action(self, parsed_args): group = self.client.groups.update(parsed_args.gid, - parsed_args.name, - parsed_args.description) + parsed_args.name, + parsed_args.description) return _make_print_data( group.gid, group.name, @@ -217,7 +219,7 @@ class DeleteGroup(Command): return parser def take_action(self, parsed_args): - group = self.client.groups.delete(parsed_args.gid) + self.client.groups.delete(parsed_args.gid) class InitGroup(ShowOne): @@ -238,29 +240,24 @@ class InitGroup(ShowOne): def get_parser(self, prog_name): parser = super(InitGroup, self).get_parser(prog_name) parser.add_argument('config', metavar='', - help="Configuration file including parameters of the new group") + help=("Configuration file including parameters" + " of the new group")) return parser def take_action(self, parsed_args): config = ConfigParser() config.read(parsed_args.config) - group_name = None group_description = None keypair_name = None keypair_is_default = True securitygroup_name = None securitygroup_is_default = True - securitygroup_rules= [] - network_cidr = None network_name = None network_is_admin = True network_gateway_ip = None network_dns_nameservers = [] - network_ext_router_id = None proxy_name = None - proxy_flavor = None - proxy_image = None try: group_name = config.get('group', 'name') @@ -275,7 +272,7 @@ class InitGroup(ShowOne): try: securitygroup_rules = config.get('securitygroup', 'rules').split() securitygroup_rules = \ - [utils.keyvalue_to_dict(r) for r in securitygroup_rules] + [utils.keyvalue_to_dict(r) for r in securitygroup_rules] except argparse.ArgumentTypeError: raise exceptions.CommandError(( "Could not create a securitygroup: " @@ -301,11 +298,15 @@ class InitGroup(ShowOne): keypair_name = config.get('keypair', 'name') keypair_is_default = config.get('keypair', 'is_default') securitygroup_name = config.get('securitygroup', 'name') - securitygroup_is_default = config.get('securitygroup', 'is_default') + securitygroup_is_default = config.get( + 'securitygroup', + 'is_default') network_name = config.get('network', 'name') network_is_admin = config.get('network', 'is_admin') network_gateway_ip = config.get('network', 'gateway_ip') - network_dns_nameservers = config.get('network', 'dns_nameservers').split() + network_dns_nameservers = config.get( + 'network', + 'dns_nameservers').split() except NoOptionError: pass @@ -313,21 +314,21 @@ class InitGroup(ShowOne): keypair = self.client.keypairs.create(group.gid, keypair_name, keypair_is_default) securitygroup = self.client.securitygroups.create( - group.gid, - securitygroup_name, - securitygroup_is_default, - securitygroup_rules) + group.gid, + securitygroup_name, + securitygroup_is_default, + securitygroup_rules) network = self.client.networks.create( - group.gid, network_cidr, network_name, - network_is_admin, network_gateway_ip, - network_dns_nameservers, - network_ext_router_id) + group.gid, network_cidr, network_name, + network_is_admin, network_gateway_ip, + network_dns_nameservers, + network_ext_router_id) proxy = self.client.proxy.create( - group.gid, name=proxy_name, - nova_flavor_id=proxy_flavor, - glance_image_id=proxy_image, - keypair_id=keypair.keypair_id, - securitygroup_ids=[securitygroup.securitygroup_id]) + group.gid, name=proxy_name, + nova_flavor_id=proxy_flavor, + glance_image_id=proxy_image, + keypair_id=keypair.keypair_id, + securitygroup_ids=[securitygroup.securitygroup_id]) columns = ['gid', 'keypair_id', 'securitygroup_id', 'network_id', 'proxy_pid', 'proxy_name'] @@ -335,4 +336,3 @@ class InitGroup(ShowOne): network.network_id, proxy.pid, proxy.name] return columns, data - diff --git a/rackclient/v1/command/keypairs.py b/rackclient/v1/command/keypairs.py index fbbae13..5da1f67 100644 --- a/rackclient/v1/command/keypairs.py +++ b/rackclient/v1/command/keypairs.py @@ -115,7 +115,8 @@ class CreateKeypair(ShowOne): help="Name of the new keypair") parser.add_argument('--is-default', metavar='', default=False, - help="Defaults to the default keypair of the group") + help=("Defaults to the default keypair of" + " the group")) return parser def take_action(self, parsed_args): @@ -195,5 +196,4 @@ class DeleteKeypair(Command): return parser def take_action(self, parsed_args): - keypair = self.client.keypairs.delete(self.gid, parsed_args.keypair_id) - + self.client.keypairs.delete(self.gid, parsed_args.keypair_id) diff --git a/rackclient/v1/command/montecarlo.py b/rackclient/v1/command/montecarlo.py index 2bb4536..834844c 100644 --- a/rackclient/v1/command/montecarlo.py +++ b/rackclient/v1/command/montecarlo.py @@ -97,4 +97,3 @@ class Montecarlo(ShowOne): data = [process.pid, process.ppid, cmd] return columns, data - diff --git a/rackclient/v1/command/networks.py b/rackclient/v1/command/networks.py index e333d75..72c1896 100644 --- a/rackclient/v1/command/networks.py +++ b/rackclient/v1/command/networks.py @@ -125,7 +125,8 @@ class CreateNetwork(ShowOne): help="Gateway ip address of the new network") parser.add_argument('--dns-nameserver', metavar='', dest='dns_nameservers', action='append', - help="DNS server for the new network (Can be repeated)") + help=("DNS server for the new network " + "(Can be repeated)")) parser.add_argument('--ext-router-id', metavar='', help="Router id the new network connects to") @@ -174,6 +175,5 @@ class DeleteNetwork(Command): return parser def take_action(self, parsed_args): - network = self.client.networks.delete(self.gid, - parsed_args.network_id) - + self.client.networks.delete(self.gid, + parsed_args.network_id) diff --git a/rackclient/v1/command/processes.py b/rackclient/v1/command/processes.py index 1d11622..b66743f 100644 --- a/rackclient/v1/command/processes.py +++ b/rackclient/v1/command/processes.py @@ -62,10 +62,12 @@ class PS(Lister): def _make_print_data(pid, ppid, name, nova_instance_id, nova_flavor_id, glance_image_id, keypair_id, securitygroup_ids, networks, - userdata, args, app_status, gid, user_id, project_id, status=None): + userdata, args, app_status, gid, user_id, project_id, + status=None): columns = ['pid', 'ppid', 'name', 'nova_instance_id', 'nova_flavor_id', - 'glance_image_id', 'keypair_id', 'securitygroup_ids', 'networks', - 'userdata', 'args', 'app_status', 'gid', 'user_id', 'project_id'] + 'glance_image_id', 'keypair_id', 'securitygroup_ids', + 'networks', 'userdata', 'args', 'app_status', 'gid', 'user_id', + 'project_id'] data = [pid, ppid, name, nova_instance_id, nova_flavor_id, glance_image_id, keypair_id, securitygroup_ids, networks, userdata, args, app_status, gid, user_id, project_id] @@ -169,7 +171,8 @@ class Boot(ShowOne): help="Userdata file path") parser.add_argument('--args', metavar='', type=utils.keyvalue_to_dict, - help="Key-value pairs to be passed to metadata server") + help=("Key-value pairs to be passed to " + "metadata server")) return parser @@ -183,15 +186,15 @@ class Boot(ShowOne): "Can't open '%s'" % parsed_args.userdata) process = self.client.processes.create( - gid=self.gid, - ppid=parsed_args.ppid, - name=parsed_args.name, - nova_flavor_id=parsed_args.flavor, - glance_image_id=parsed_args.image, - keypair_id=parsed_args.keypair, - securitygroup_ids=parsed_args.securitygroup_ids, - userdata=userdata, - args=parsed_args.args) + gid=self.gid, + ppid=parsed_args.ppid, + name=parsed_args.name, + nova_flavor_id=parsed_args.flavor, + glance_image_id=parsed_args.image, + keypair_id=parsed_args.keypair, + securitygroup_ids=parsed_args.securitygroup_ids, + userdata=userdata, + args=parsed_args.args) sg_ids = process.securitygroup_ids if sg_ids: @@ -245,5 +248,4 @@ class Kill(Command): return parser def take_action(self, parsed_args): - process = self.client.processes.delete(self.gid, parsed_args.pid) - + self.client.processes.delete(self.gid, parsed_args.pid) diff --git a/rackclient/v1/command/proxy.py b/rackclient/v1/command/proxy.py index aecc089..8655665 100644 --- a/rackclient/v1/command/proxy.py +++ b/rackclient/v1/command/proxy.py @@ -25,9 +25,9 @@ def _make_print_data(pid, ppid, name, nova_instance_id, nova_flavor_id, userdata, args, app_status, fs_endpoint, ipc_endpoint, shm_endpoint, gid, user_id, project_id, status=None): columns = ['pid', 'ppid', 'name', 'nova_instance_id', 'nova_flavor_id', - 'glance_image_id', 'keypair_id', 'securitygroup_ids', 'networks', - 'userdata', 'args', 'app_status', 'fs_endpoint', 'ipc_endpoint', - 'shm_endpoint', 'gid', 'user_id', 'project_id'] + 'glance_image_id', 'keypair_id', 'securitygroup_ids', + 'networks', 'userdata', 'args', 'app_status', 'fs_endpoint', + 'ipc_endpoint', 'shm_endpoint', 'gid', 'user_id', 'project_id'] data = [pid, ppid, name, nova_instance_id, nova_flavor_id, glance_image_id, keypair_id, securitygroup_ids, networks, userdata, args, app_status, fs_endpoint, ipc_endpoint, @@ -117,23 +117,27 @@ class CreateProxy(ShowOne): parser.add_argument('--securitygroup', metavar='', dest='securitygroup', action='append', default=[], - help="Securitygroup id the rack-proxy process belongs to (Can be repeated)") + help=("Securitygroup id the rack-proxy process " + "belongs to (Can be repeated)")) parser.add_argument('--flavor', metavar='', required=True, - help="(Required) Flavor id of the rack-proxy process") + help=("(Required) Flavor id of " + "the rack-proxy process")) parser.add_argument('--image', metavar='', required=True, - help="(Required) Image id that registered on Glance of the rack-proxy process") + help=("(Required) Image id that registered " + "on Glance of the rack-proxy process")) return parser def take_action(self, parsed_args): - proxy = self.client.proxy.create(self.gid, - name=parsed_args.name, - nova_flavor_id=parsed_args.flavor, - glance_image_id=parsed_args.image, - keypair_id=parsed_args.keypair, - securitygroup_ids=parsed_args.securitygroup) + proxy = self.client.proxy.create( + self.gid, + ame=parsed_args.name, + ova_flavor_id=parsed_args.flavor, + lance_image_id=parsed_args.image, + eypair_id=parsed_args.keypair, + ecuritygroup_ids=parsed_args.securitygroup) sg_ids = proxy.securitygroup_ids if sg_ids: @@ -236,4 +240,3 @@ class UpdateProxy(ShowOne): proxy.user_id, proxy.project_id ) - diff --git a/rackclient/v1/command/securitygroups.py b/rackclient/v1/command/securitygroups.py index 1d74017..a33dd16 100644 --- a/rackclient/v1/command/securitygroups.py +++ b/rackclient/v1/command/securitygroups.py @@ -55,7 +55,8 @@ class ListSecuritygroups(Lister): securitygroups = self.client.securitygroups.list(self.gid) return ( ('securitygroup_id', 'name', 'is_default', 'status'), - ((s.securitygroup_id, s.name, s.is_default, s.status) for s in securitygroups) + ((s.securitygroup_id, s.name, s.is_default, s.status) + for s in securitygroups) ) @@ -81,8 +82,9 @@ class ShowSecuritygroup(ShowOne): return parser def take_action(self, parsed_args): - securitygroup = self.client.securitygroups.get(self.gid, - parsed_args.securitygroup_id) + securitygroup = self.client.securitygroups.get( + self.gid, + parsed_args.securitygroup_id) return _make_print_data( securitygroup.securitygroup_id, securitygroup.name, @@ -116,11 +118,15 @@ class CreateSecuritygroup(ShowOne): help="Name of the new securitygroup") parser.add_argument('--is-default', metavar='', default=False, - help="Defaults to the default securitygroup of the group") + help=("Defaults to the default securitygroup " + "of the group")) parser.add_argument('--rule', - metavar=(""), + metavar=(""), action='append', type=utils.keyvalue_to_dict, dest='rules', @@ -130,16 +136,18 @@ class CreateSecuritygroup(ShowOne): "port_range_max: Starting port range, " "port_range_min: Ending port range, " "remote_ip_prefix: CIDR to match on, " - "remote_securitygroup_id: Remote securitygroup id " + "remote_securitygroup_id: " + "Remote securitygroup id " "to apply rule. (Can be repeated)")) return parser def take_action(self, parsed_args): - securitygroup = self.client.securitygroups.create(self.gid, - parsed_args.name, - parsed_args.is_default, - parsed_args.rules) + securitygroup = self.client.securitygroups.create( + self.gid, + parsed_args.name, + parsed_args.is_default, + parsed_args.rules) return _make_print_data( securitygroup.securitygroup_id, @@ -173,13 +181,15 @@ class UpdateSecuritygroup(ShowOne): help="Securitygroup ID") parser.add_argument('--is-default', metavar='', required=True, - help="Defaults to the default securitygroup of the group") + help=("Defaults to the default securitygroup " + "of the group")) return parser def take_action(self, parsed_args): - securitygroup = self.client.securitygroups.update(self.gid, - parsed_args.securitygroup_id, - parsed_args.is_default) + securitygroup = self.client.securitygroups.update( + self.gid, + parsed_args.securitygroup_id, + parsed_args.is_default) return _make_print_data( securitygroup.securitygroup_id, securitygroup.name, @@ -213,6 +223,6 @@ class DeleteSecuritygroup(Command): return parser def take_action(self, parsed_args): - securitygroup = self.client.securitygroups.delete(self.gid, - parsed_args.securitygroup_id) - + self.client.securitygroups.delete( + self.gid, + parsed_args.securitygroup_id) diff --git a/rackclient/v1/keypairs.py b/rackclient/v1/keypairs.py index 46c4db9..92201d5 100644 --- a/rackclient/v1/keypairs.py +++ b/rackclient/v1/keypairs.py @@ -43,7 +43,8 @@ class KeypairManager(base.Manager): :param keypair_id: ID of the keypair to get. :rtype: Keypair. """ - return self._get("/groups/%s/keypairs/%s" % (gid, keypair_id), "keypair") + return self._get("/groups/%s/keypairs/%s" % + (gid, keypair_id), "keypair") def create(self, gid, name=None, is_default=False): """ @@ -84,7 +85,8 @@ class KeypairManager(base.Manager): "is_default": is_default } } - return self._update("/groups/%s/keypairs/%s" % (gid, keypair_id), body, "keypair") + return self._update("/groups/%s/keypairs/%s" % + (gid, keypair_id), body, "keypair") def delete(self, gid, keypair_id): """ diff --git a/rackclient/v1/networks.py b/rackclient/v1/networks.py index 3c68762..8a33d8d 100644 --- a/rackclient/v1/networks.py +++ b/rackclient/v1/networks.py @@ -44,9 +44,11 @@ class NetworkManager(base.Manager): :param network_id: ID of the network to get. :rtype: Network. """ - return self._get("/groups/%s/networks/%s" % (gid, network_id), "network") + return self._get("/groups/%s/networks/%s" % + (gid, network_id), "network") - def create(self, gid, cidr, name=None, is_admin=False, gateway=None, dns_nameservers=None, ext_router_id=None): + def create(self, gid, cidr, name=None, is_admin=False, + gateway=None, dns_nameservers=None, ext_router_id=None): """ Create a network. @@ -72,7 +74,7 @@ class NetworkManager(base.Manager): return True if not _is_valid_cidr(cidr): - raise exceptions.CommandError("cidr must be a CIDR.") + raise exceptions.CommandError("cidr must be a CIDR.") if is_admin: try: @@ -83,7 +85,8 @@ class NetworkManager(base.Manager): if gateway and not netaddr.valid_ipv4(gateway): raise exceptions.CommandError("gateway must be a IP address") - if dns_nameservers is not None and not isinstance(dns_nameservers, list): + if dns_nameservers is not None and not isinstance( + dns_nameservers, list): raise exceptions.CommandError("dns_nameservers must be a list") body = { @@ -101,7 +104,7 @@ class NetworkManager(base.Manager): def delete(self, gid, network_id): """ Delete a network. - + :param gid: ID of the group. :param network_id: ID of the network to delete. """ diff --git a/rackclient/v1/processes.py b/rackclient/v1/processes.py index 9007508..fd8ba88 100644 --- a/rackclient/v1/processes.py +++ b/rackclient/v1/processes.py @@ -46,7 +46,7 @@ class ProcessManager(base.Manager): return self._get("/groups/%s/processes/%s" % (gid, pid), "process") def create(self, gid, ppid=None, **kwargs): - ''' + """ Create a process. If you give a ppid(Parent process ID), @@ -62,10 +62,11 @@ class ProcessManager(base.Manager): :param list securitygroup_ids: List of IDs of securitygroups :param userdata: file type object or string of script :param dict args: Dict of key-value pairs to be stored as metadata - ''' + """ securitygroup_ids = kwargs.get('securitygroup_ids') - if securitygroup_ids is not None and not isinstance(securitygroup_ids, list): + if securitygroup_ids is not None and not isinstance( + securitygroup_ids, list): raise exceptions.CommandError("securitygroup_ids must be a list") userdata = kwargs.get('userdata') @@ -105,12 +106,13 @@ class ProcessManager(base.Manager): "app_status": app_status } } - return self._update("/groups/%s/processes/%s" % (gid, pid), body, "process") + return self._update("/groups/%s/processes/%s" % + (gid, pid), body, "process") def delete(self, gid, pid): """ Delete a process. - + :param gid: ID of the group. :param pid: ID of the process to delete. """ diff --git a/rackclient/v1/proxy.py b/rackclient/v1/proxy.py index 20380a6..8ee2605 100644 --- a/rackclient/v1/proxy.py +++ b/rackclient/v1/proxy.py @@ -33,10 +33,11 @@ class ProxyManager(base.Manager): :param gid: ID of the group. :rtype: Process """ - return self._get("/groups/%s/proxy" % (gid), "proxy") + return self._get("/groups/%s/proxy" % gid, "proxy") - def create(self, gid, name=None, nova_flavor_id=None, glance_image_id=None, keypair_id=None, - securitygroup_ids=None, userdata=None, args=None): + def create(self, gid, name=None, nova_flavor_id=None, glance_image_id=None, + keypair_id=None, securitygroup_ids=None, userdata=None, + args=None): """ Create a rack-proxy process. @@ -50,7 +51,8 @@ class ProxyManager(base.Manager): :param dict args: Dict of key-value pairs to be stored as metadata """ - if securitygroup_ids is not None and not isinstance(securitygroup_ids, list): + if securitygroup_ids is not None and not isinstance( + securitygroup_ids, list): raise exceptions.CommandError("securitygroup_ids must be a list") if userdata: @@ -74,12 +76,14 @@ class ProxyManager(base.Manager): } return self._create("/groups/%s/proxy" % gid, body, "proxy") - def update(self, gid, shm_endpoint=None, ipc_endpoint=None, fs_endpoint=None, app_status=None): + def update(self, gid, shm_endpoint=None, ipc_endpoint=None, + fs_endpoint=None, app_status=None): """ Update parameters of a rack-proxy process. :param gid: ID of a group - :param shm_endpoint: An endpoint of Shared memory. Arbitrary string value. + :param shm_endpoint: An endpoint of Shared memory. + Arbitrary string value. :param ipc_endpoint: An endpoint of IPC. Arbitrary string value. :param fs_endpoint: An endpoint of File System. Arbitrary string value. :param app_status: Application layer status of a rack-proxy process. diff --git a/rackclient/v1/securitygroups.py b/rackclient/v1/securitygroups.py index 228aa46..818b112 100644 --- a/rackclient/v1/securitygroups.py +++ b/rackclient/v1/securitygroups.py @@ -43,9 +43,11 @@ class SecuritygroupManager(base.Manager): :param securitygroup_id: ID of the securitygroup to get. :rtype: Securitygroup. """ - return self._get("/groups/%s/securitygroups/%s" % (gid, securitygroup_id), "securitygroup") + return self._get("/groups/%s/securitygroups/%s" % + (gid, securitygroup_id), "securitygroup") - def create(self, gid, name=None, is_default=False, securitygroup_rules=None): + def create(self, gid, name=None, is_default=False, + securitygroup_rules=None): """ Create a securitygroup. @@ -61,7 +63,8 @@ class SecuritygroupManager(base.Manager): if securitygroup_rules is not None: if not isinstance(securitygroup_rules, list): - raise exceptions.CommandError("securitygroup_rules must be a list") + raise exceptions.CommandError( + "securitygroup_rules must be a list") body = { "securitygroup": { @@ -70,7 +73,8 @@ class SecuritygroupManager(base.Manager): "securitygrouprules": securitygroup_rules } } - return self._create("/groups/%s/securitygroups" % gid, body, "securitygroup") + return self._create("/groups/%s/securitygroups" % + gid, body, "securitygroup") def update(self, gid, securitygroup_id, is_default=False): """ @@ -90,7 +94,8 @@ class SecuritygroupManager(base.Manager): "is_default": is_default, } } - return self._update("/groups/%s/securitygroups/%s" % (gid, securitygroup_id), body, "securitygroup") + return self._update("/groups/%s/securitygroups/%s" % + (gid, securitygroup_id), body, "securitygroup") def delete(self, gid, securitygroup_id): """ diff --git a/tox.ini b/tox.ini index 1a52750..64b81e6 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ setenv = VIRTUAL_ENV={envdir} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = - find . -type f -name "*.pyc" -delete + /usr/bin/find . -type f -name "*.pyc" -delete python setup.py testr --testr-args='{posargs}' [testenv:pep8]