diff --git a/README.rst b/README.rst index c6debc370..834ab7d4b 100644 --- a/README.rst +++ b/README.rst @@ -83,6 +83,8 @@ You'll find complete documentation on the shell by running Delete the backup schedule for a server. boot Boot a new server. delete Immediately shut down and delete a server. + flavor-create Create a new flavor + flavor-delete Delete a specific flavor flavor-list Print a list of available 'flavors' (sizes of servers). floating-ip-create Allocate a floating IP to the current tenant. diff --git a/novaclient/v1_1/flavors.py b/novaclient/v1_1/flavors.py index 6eb1e2c4b..8092598b1 100644 --- a/novaclient/v1_1/flavors.py +++ b/novaclient/v1_1/flavors.py @@ -39,3 +39,41 @@ class FlavorManager(base.ManagerWithFind): :rtype: :class:`Flavor` """ return self._get("/flavors/%s" % base.getid(flavor), "flavor") + + def delete(self, flavor): + """ + Delete a specific flavor. + + :param flavor: The ID of the :class:`Flavor` to get. + :param purge: Whether to purge record from the database + """ + self._delete("/flavors/%s" % base.getid(flavor)) + + def create(self, name, ram, vcpus, disk, flavorid, + swap=0, rxtx_factor=1): + """ + Create (allocate) a floating ip for a tenant + + :param name: Descriptive name of the flavor + :param ram: Memory in MB for the flavor + :param vcpu: Number of VCPUs for the flavor + :param disk: Size of local disk in GB + :param flavorid: Integer ID for the flavor + :param swap: Swap space in MB + :param rxtx_factor: RX/TX factor + :rtype: :class:`Flavor` + """ + + body = { + "flavor": { + "name": name, + "ram": int(ram), + "vcpus": int(vcpus), + "disk": int(disk), + "id": int(flavorid), + "swap": int(swap), + "rxtx_factor": int(rxtx_factor), + } + } + + return self._create("/flavors", body, "flavor") diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index 550880fec..79facdc21 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -294,9 +294,7 @@ def _translate_flavor_keys(collection): setattr(item, to_key, item._info[from_key]) -def do_flavor_list(cs, args): - """Print a list of available 'flavors' (sizes of servers).""" - flavors = cs.flavors.list() +def _print_flavor_list(flavors): _translate_flavor_keys(flavors) utils.print_list(flavors, [ 'ID', @@ -308,6 +306,50 @@ def do_flavor_list(cs, args): 'RXTX_Factor']) +def do_flavor_list(cs, args): + """Print a list of available 'flavors' (sizes of servers).""" + flavors = cs.flavors.list() + _print_flavor_list(flavors) + + +@utils.arg('id', + metavar='', + help="Unique ID of the flavor to delete") +def do_flavor_delete(cs, args): + """Delete a specific flavor""" + cs.flavors.delete(args.id) + + +@utils.arg('name', + metavar='', + help="Name of the new flavor") +@utils.arg('id', + metavar='', + help="Unique integer ID for the new flavor") +@utils.arg('ram', + metavar='', + help="Memory size in MB") +@utils.arg('disk', + metavar='', + help="Disk size in GB") +@utils.arg('vcpus', + metavar='', + help="Number of vcpus") +@utils.arg('--swap', + metavar='', + help="Swap space size in MB (default 0)", + default=0) +@utils.arg('--rxtx-factor', + metavar='', + help="RX/TX factor (default 1)", + default=1) +def do_flavor_create(cs, args): + """Create a new flavor""" + f = cs.flavors.create(args.name, args.ram, args.vcpus, args.disk, args.id, + args.swap, args.rxtx_factor) + _print_flavor_list([f]) + + def do_image_list(cs, args): """Print a list of available images to boot from.""" image_list = cs.images.list() diff --git a/tests/v1_1/fakes.py b/tests/v1_1/fakes.py index 008697aad..5c047f9ab 100644 --- a/tests/v1_1/fakes.py +++ b/tests/v1_1/fakes.py @@ -348,6 +348,12 @@ class FakeHTTPClient(base_client.HTTPClient): def get_flavors_2(self, **kw): return (200, {'flavor': self.get_flavors_detail()[1]['flavors'][1]}) + def delete_flavors_flavordelete(self, **kw): + return (202, None) + + def post_flavors(self, body, **kw): + return (202, {'flavor': self.get_flavors_detail()[1]['flavors'][0]}) + # # Floating ips # diff --git a/tests/v1_1/test_flavors.py b/tests/v1_1/test_flavors.py index 7ab9eda98..1f9d5719f 100644 --- a/tests/v1_1/test_flavors.py +++ b/tests/v1_1/test_flavors.py @@ -35,3 +35,25 @@ class FlavorsTest(utils.TestCase): self.assertEqual(f.name, '512 MB Server') self.assertRaises(exceptions.NotFound, cs.flavors.find, disk=12345) + + def test_create(self): + f = cs.flavors.create("flavorcreate", 512, 1, 10, 1234) + + body = { + "flavor": { + "name": "flavorcreate", + "ram": 512, + "vcpus": 1, + "disk": 10, + "id": 1234, + "swap": 0, + "rxtx_factor": 1, + } + } + + cs.assert_called('POST', '/flavors', body) + self.assertTrue(isinstance(f, flavors.Flavor)) + + def test_delete(self): + cs.flavors.delete("flavordelete") + cs.assert_called('DELETE', '/flavors/flavordelete') diff --git a/tests/v1_1/test_shell.py b/tests/v1_1/test_shell.py index cb15aad68..67de2151c 100644 --- a/tests/v1_1/test_shell.py +++ b/tests/v1_1/test_shell.py @@ -328,3 +328,26 @@ class ShellTest(utils.TestCase): 'start=2000-01-20T00:00:00&' + 'end=2005-02-01T00:00:00&' + 'detailed=1') + + def test_flavor_delete(self): + self.run_command("flavor-delete flavordelete") + self.assert_called('DELETE', '/flavors/flavordelete') + + def test_flavor_create(self): + self.run_command("flavor-create flavorcreate " + "1234 512 10 1 --swap 1024") + + body = { + "flavor": { + "name": "flavorcreate", + "ram": 512, + "vcpus": 1, + "disk": 10, + "id": 1234, + "swap": 1024, + "rxtx_factor": 1, + } + } + + self.assert_called('POST', '/flavors', body, pos=-2) + self.assert_called('GET', '/flavors/1')