summaryrefslogtreecommitdiff
path: root/novaclient/v2
diff options
context:
space:
mode:
Diffstat (limited to 'novaclient/v2')
-rw-r--r--novaclient/v2/__init__.py16
-rw-r--r--novaclient/v2/agents.py67
-rw-r--r--novaclient/v2/aggregates.py95
-rw-r--r--novaclient/v2/availability_zones.py52
-rw-r--r--novaclient/v2/certs.py48
-rw-r--r--novaclient/v2/client.py239
-rw-r--r--novaclient/v2/cloudpipe.py61
-rw-r--r--novaclient/v2/contrib/__init__.py0
-rw-r--r--novaclient/v2/contrib/assisted_volume_snapshots.py48
-rw-r--r--novaclient/v2/contrib/baremetal.py339
-rw-r--r--novaclient/v2/contrib/cells.py74
-rw-r--r--novaclient/v2/contrib/deferred_delete.py28
-rw-r--r--novaclient/v2/contrib/host_evacuate.py64
-rw-r--r--novaclient/v2/contrib/host_evacuate_live.py68
-rw-r--r--novaclient/v2/contrib/host_servers_migrate.py51
-rw-r--r--novaclient/v2/contrib/instance_action.py72
-rw-r--r--novaclient/v2/contrib/list_extensions.py46
-rw-r--r--novaclient/v2/contrib/metadata_extensions.py47
-rw-r--r--novaclient/v2/contrib/migrations.py91
-rw-r--r--novaclient/v2/contrib/server_external_events.py43
-rw-r--r--novaclient/v2/contrib/tenant_networks.py82
-rw-r--r--novaclient/v2/fixed_ips.py56
-rw-r--r--novaclient/v2/flavor_access.py70
-rw-r--r--novaclient/v2/flavors.py207
-rw-r--r--novaclient/v2/floating_ip_dns.py121
-rw-r--r--novaclient/v2/floating_ip_pools.py32
-rw-r--r--novaclient/v2/floating_ips.py59
-rw-r--r--novaclient/v2/floating_ips_bulk.py58
-rw-r--r--novaclient/v2/fping.py64
-rw-r--r--novaclient/v2/hosts.py70
-rw-r--r--novaclient/v2/hypervisors.py92
-rw-r--r--novaclient/v2/images.py101
-rw-r--r--novaclient/v2/keypairs.py92
-rw-r--r--novaclient/v2/limits.py100
-rw-r--r--novaclient/v2/networks.py156
-rw-r--r--novaclient/v2/quota_classes.py44
-rw-r--r--novaclient/v2/quotas.py72
-rw-r--r--novaclient/v2/security_group_default_rules.py81
-rw-r--r--novaclient/v2/security_group_rules.py78
-rw-r--r--novaclient/v2/security_groups.py96
-rw-r--r--novaclient/v2/server_groups.py71
-rw-r--r--novaclient/v2/servers.py1274
-rw-r--r--novaclient/v2/services.py75
-rw-r--r--novaclient/v2/shell.py4447
-rw-r--r--novaclient/v2/usage.py61
-rw-r--r--novaclient/v2/versions.py35
-rw-r--r--novaclient/v2/virtual_interfaces.py33
-rw-r--r--novaclient/v2/volume_snapshots.py90
-rw-r--r--novaclient/v2/volume_types.py77
-rw-r--r--novaclient/v2/volumes.py165
50 files changed, 9608 insertions, 0 deletions
<
diff --git a/novaclient/v2/__init__.py b/novaclient/v2/__init__.py
new file mode 100644
index 0000000..21d7c4f
--- /dev/null
+++ b/novaclient/v2/__init__.py
@@ -0,0 +1,16 @@
1#
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient.v2.client import Client # noqa
diff --git a/novaclient/v2/agents.py b/novaclient/v2/agents.py
new file mode 100644
index 0000000..b5372cb
--- /dev/null
+++ b/novaclient/v2/agents.py
@@ -0,0 +1,67 @@
1# Copyright 2012 IBM Corp.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17agent interface
18"""
19
20from novaclient import base
21
22
23class Agent(base.Resource):
24 def __repr__(self):
25 return "<Agent: %s>" % self.agent
26
27 def _add_details(self, info):
28 dico = 'resource' in info and info['resource'] or info
29 for (k, v) in dico.items():
30 setattr(self, k, v)
31
32
33class AgentsManager(base.ManagerWithFind):
34 resource_class = Agent
35
36 def list(self, hypervisor=None):
37 """List all agent builds."""
38 url = "/os-agents"
39 if hypervisor:
40 url = "/os-agents?hypervisor=%s" % hypervisor
41 return self._list(url, "agents")
42
43 def _build_update_body(self, version, url, md5hash):
44 return {'para': {'version': version,
45 'url': url,
46 'md5hash': md5hash}}
47
48 def update(self, id, version,
49 url, md5hash):
50 """Update an existing agent build."""
51 body = self._build_update_body(version, url, md5hash)
52 return self._update('/os-agents/%s' % id, body, 'agent')
53
54 def create(self, os, architecture, version,
55 url, md5hash, hypervisor):
56 """Create a new agent build."""
57 body = {'agent': {'hypervisor': hypervisor,
58 'os': os,
59 'architecture': architecture,
60 'version': version,
61 'url': url,
62 'md5hash': md5hash}}
63 return self._create('/os-agents', body, 'agent')
64
65 def delete(self, id):
66 """Deletes an existing agent build."""
67 self._delete('/os-agents/%s' % id)
diff --git a/novaclient/v2/aggregates.py b/novaclient/v2/aggregates.py
new file mode 100644
index 0000000..c2df315
--- /dev/null
+++ b/novaclient/v2/aggregates.py
@@ -0,0 +1,95 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Aggregate interface."""
17
18from novaclient import base
19
20
21class Aggregate(base.Resource):
22 """An aggregates is a collection of compute hosts."""
23
24 def __repr__(self):
25 return "<Aggregate: %s>" % self.id
26
27 def update(self, values):
28 """Update the name and/or availability zone."""
29 return self.manager.update(self, values)
30
31 def add_host(self, host):
32 return self.manager.add_host(self, host)
33
34 def remove_host(self, host):
35 return self.manager.remove_host(self, host)
36
37 def set_metadata(self, metadata):
38 return self.manager.set_metadata(self, metadata)
39
40 def delete(self):
41 self.manager.delete(self)
42
43
44class AggregateManager(base.ManagerWithFind):
45 resource_class = Aggregate
46
47 def list(self):
48 """Get a list of os-aggregates."""
49 return self._list('/os-aggregates', 'aggregates')
50
51 def create(self, name, availability_zone):
52 """Create a new aggregate."""
53 body = {'aggregate': {'name': name,
54 'availability_zone': availability_zone}}
55 return self._create('/os-aggregates', body, 'aggregate')
56
57 def get(self, aggregate):
58 """Get details of the specified aggregate."""
59 return self._get('/os-aggregates/%s' % (base.getid(aggregate)),
60 "aggregate")
61
62 # NOTE:(dtroyer): utils.find_resource() uses manager.get() but we need to
63 # keep the API backward compatible
64 def get_details(self, aggregate):
65 """Get details of the specified aggregate."""
66 return self.get(aggregate)
67
68 def update(self, aggregate, values):
69 """Update the name and/or availability zone."""
70 body = {'aggregate': values}
71 return self._update("/os-aggregates/%s" % base.getid(aggregate),
72 body,
73 "aggregate")
74
75 def add_host(self, aggregate, host):
76 """Add a host into the Host Aggregate."""
77 body = {'add_host': {'host': host}}
78 return self._create("/os-aggregates/%s/action" % base.getid(aggregate),
79 body, "aggregate")
80
81 def remove_host(self, aggregate, host):
82 """Remove a host from the Host Aggregate."""
83 body = {'remove_host': {'host': host}}
84 return self._create("/os-aggregates/%s/action" % base.getid(aggregate),
85 body, "aggregate")
86
87 def set_metadata(self, aggregate, metadata):
88 """Set a aggregate metadata, replacing the existing metadata."""
89 body = {'set_metadata': {'metadata': metadata}}
90 return self._create("/os-aggregates/%s/action" % base.getid(aggregate),
91 body, "aggregate")
92
93 def delete(self, aggregate):
94 """Delete the specified aggregates."""
95 self._delete('/os-aggregates/%s' % (base.getid(aggregate)))
diff --git a/novaclient/v2/availability_zones.py b/novaclient/v2/availability_zones.py
new file mode 100644
index 0000000..bf59037
--- /dev/null
+++ b/novaclient/v2/availability_zones.py
@@ -0,0 +1,52 @@
1# Copyright 2011 OpenStack Foundation
2# Copyright 2013 IBM Corp.
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17"""
18Availability Zone interface (1.1 extension).
19"""
20
21from novaclient import base
22
23
24class AvailabilityZone(base.Resource):
25 """
26 An availability zone object.
27 """
28 NAME_ATTR = 'display_name'
29
30 def __repr__(self):
31 return "<AvailabilityZone: %s>" % self.zoneName
32
33
34class AvailabilityZoneManager(base.ManagerWithFind):
35 """
36 Manage :class:`AvailabilityZone` resources.
37 """
38 resource_class = AvailabilityZone
39 return_parameter_name = "availabilityZoneInfo"
40
41 def list(self, detailed=True):
42 """
43 Get a list of all availability zones.
44
45 :rtype: list of :class:`AvailabilityZone`
46 """
47 if detailed is True:
48 return self._list("/os-availability-zone/detail",
49 self.return_parameter_name)
50 else:
51 return self._list("/os-availability-zone",
52 self.return_parameter_name)
diff --git a/novaclient/v2/certs.py b/novaclient/v2/certs.py
new file mode 100644
index 0000000..2c3006c
--- /dev/null
+++ b/novaclient/v2/certs.py
@@ -0,0 +1,48 @@
1# Copyright 2010 Jacob Kaplan-Moss
2
3# Copyright 2011 OpenStack Foundation
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18"""
19Certificate interface.
20"""
21
22from novaclient import base
23
24
25class Certificate(base.Resource):
26 def __repr__(self):
27 return ("<Certificate: private_key=[%s bytes] data=[%s bytes]>" %
28 (len(self.private_key) if self.private_key else 0,
29 len(self.data)))
30
31
32class CertificateManager(base.Manager):
33 """
34 Manage :class:`Certificate` resources.
35 """
36 resource_class = Certificate
37
38 def create(self):
39 """
40 Create a x509 certificate for a user in tenant.
41 """
42 return self._create('/os-certificates', {}, 'certificate')
43
44 def get(self):
45 """
46 Get root certificate.
47 """
48 return self._get("/os-certificates/root", 'certificate')
diff --git a/novaclient/v2/client.py b/novaclient/v2/client.py
new file mode 100644
index 0000000..386c649
--- /dev/null
+++ b/novaclient/v2/client.py
@@ -0,0 +1,239 @@
1# Copyright 2012 OpenStack Foundation
2# Copyright 2013 IBM Corp.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import client
17from novaclient.v2 import agents
18from novaclient.v2 import aggregates
19from novaclient.v2 import availability_zones
20from novaclient.v2 import certs
21from novaclient.v2 import cloudpipe
22from novaclient.v2 import fixed_ips
23from novaclient.v2 import flavor_access
24from novaclient.v2 import flavors
25from novaclient.v2 import floating_ip_dns
26from novaclient.v2 import floating_ip_pools
27from novaclient.v2 import floating_ips
28from novaclient.v2 import floating_ips_bulk
29from novaclient.v2 import fping
30from novaclient.v2 import hosts
31from novaclient.v2 import hypervisors
32from novaclient.v2 import images
33from novaclient.v2 import keypairs
34from novaclient.v2 import limits
35from novaclient.v2 import networks
36from novaclient.v2 import quota_classes
37from novaclient.v2 import quotas
38from novaclient.v2 import security_group_default_rules
39from novaclient.v2 import security_group_rules
40from novaclient.v2 import security_groups
41from novaclient.v2 import server_groups
42from novaclient.v2 import servers
43from novaclient.v2 import services
44from novaclient.v2 import usage
45from novaclient.v2 import versions
46from novaclient.v2 import virtual_interfaces
47from novaclient.v2 import volume_snapshots
48from novaclient.v2 import volume_types
49from novaclient.v2 import volumes
50
51
52class Client(object):
53 """
54 Top-level object to access the OpenStack Compute API.
55
56 Create an instance with your creds::
57
58 >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL)
59
60 Or, alternatively, you can create a client instance using the
61 keystoneclient.session API::
62
63 >>> from keystoneclient.auth.identity import v2
64 >>> from keystoneclient import session
65 >>> from novaclient.client import Client
66 >>> auth = v2.Password(auth_url=AUTH_URL,
67 username=USERNAME,
68 password=PASSWORD,
69 tenant_name=PROJECT_ID)
70 >>> sess = session.Session(auth=auth)
71 >>> nova = client.Client(VERSION, session=sess)
72
73 Then call methods on its managers::
74
75 >>> client.servers.list()
76 ...
77 >>> client.flavors.list()
78 ...
79
80 It is also possible to use an instance as a context manager in which
81 case there will be a session kept alive for the duration of the with
82 statement::
83
84 >>> with Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) as client:
85 ... client.servers.list()
86 ... client.flavors.list()
87 ...
88
89 It is also possible to have a permanent (process-long) connection pool,
90 by passing a connection_pool=True::
91
92 >>> client = Client(USERNAME, PASSWORD, PROJECT_ID,
93 ... AUTH_URL, connection_pool=True)
94 """
95
96 def __init__(self, username=None, api_key=None, project_id=None,
97 auth_url=None, insecure=False, timeout=None,
98 proxy_tenant_id=None, proxy_token=None, region_name=None,
99 endpoint_type='publicURL', extensions=None,
100 service_type='compute', service_name=None,
101 volume_service_name=None, timings=False, bypass_url=None,
102 os_cache=False, no_cache=True, http_log_debug=False,
103 auth_system='keystone', auth_plugin=None, auth_token=None,
104 cacert=None, tenant_id=None, user_id=None,
105 connection_pool=False, session=None, auth=None,
106 completion_cache=None, **kwargs):
107 # FIXME(comstud): Rename the api_key argument above when we
108 # know it's not being used as keyword argument
109
110 # NOTE(cyeoh): In the novaclient context (unlike Nova) the
111 # project_id is not the same as the tenant_id. Here project_id
112 # is a name (what the Nova API often refers to as a project or
113 # tenant name) and tenant_id is a UUID (what the Nova API
114 # often refers to as a project_id or tenant_id).
115
116 password = api_key
117 self.projectid = project_id
118 self.tenant_id = tenant_id
119 self.user_id = user_id
120 self.flavors = flavors.FlavorManager(self)
121 self.flavor_access = flavor_access.FlavorAccessManager(self)
122 self.images = images.ImageManager(self)
123 self.limits = limits.LimitsManager(self)
124 self.servers = servers.ServerManager(self)
125 self.versions = versions.VersionManager(self)
126
127 # extensions
128 self.agents = agents.AgentsManager(self)
129 self.dns_domains = floating_ip_dns.FloatingIPDNSDomainManager(self)
130 self.dns_entries = floating_ip_dns.FloatingIPDNSEntryManager(self)
131 self.cloudpipe = cloudpipe.CloudpipeManager(self)
132 self.certs = certs.CertificateManager(self)
133 self.floating_ips = floating_ips.FloatingIPManager(self)
134 self.floating_ip_pools = floating_ip_pools.FloatingIPPoolManager(self)
135 self.fping = fping.FpingManager(self)
136 self.volumes = volumes.VolumeManager(self)
137 self.volume_snapshots = volume_snapshots.SnapshotManager(self)
138 self.volume_types = volume_types.VolumeTypeManager(self)
139 self.keypairs = keypairs.KeypairManager(self)
140 self.networks = networks.NetworkManager(self)
141 self.quota_classes = quota_classes.QuotaClassSetManager(self)
142 self.quotas = quotas.QuotaSetManager(self)
143 self.security_groups = security_groups.SecurityGroupManager(self)
144 self.security_group_rules = \
145 security_group_rules.SecurityGroupRuleManager(self)
146 self.security_group_default_rules = \
147 security_group_default_rules.SecurityGroupDefaultRuleManager(self)
148 self.usage = usage.UsageManager(self)
149 self.virtual_interfaces = \
150 virtual_interfaces.VirtualInterfaceManager(self)
151 self.aggregates = aggregates.AggregateManager(self)
152 self.hosts = hosts.HostManager(self)
153 self.hypervisors = hypervisors.HypervisorManager(self)
154 self.hypervisor_stats = hypervisors.HypervisorStatsManager(self)
155 self.services = services.ServiceManager(self)
156 self.fixed_ips = fixed_ips.FixedIPsManager(self)
157 self.floating_ips_bulk = floating_ips_bulk.FloatingIPBulkManager(self)
158 self.os_cache = os_cache or not no_cache
159 self.availability_zones = \
160 availability_zones.AvailabilityZoneManager(self)
161 self.server_groups = server_groups.ServerGroupsManager(self)
162
163 # Add in any extensions...
164 if extensions:
165 for extension in extensions:
166 if extension.manager_class:
167 setattr(self, extension.name,
168 extension.manager_class(self))
169
170 self.client = client._construct_http_client(
171 username=username,
172 password=password,
173 user_id=user_id,
174 project_id=project_id,
175 tenant_id=tenant_id,
176 auth_url=auth_url,
177 auth_token=auth_token,
178 insecure=insecure,
179 timeout=timeout,
180 auth_system=auth_system,
181 auth_plugin=auth_plugin,
182 proxy_token=proxy_token,
183 proxy_tenant_id=proxy_tenant_id,
184 region_name=region_name,
185 endpoint_type=endpoint_type,
186 service_type=service_type,
187 service_name=service_name,
188 volume_service_name=volume_service_name,
189 timings=timings,
190 bypass_url=bypass_url,
191 os_cache=self.os_cache,
192 http_log_debug=http_log_debug,
193 cacert=cacert,
194 connection_pool=connection_pool,
195 session=session,
196 auth=auth,
197 **kwargs)
198
199 self.completion_cache = completion_cache
200
201 def write_object_to_completion_cache(self, obj):
202 if self.completion_cache:
203 self.completion_cache.write_object(obj)
204
205 def clear_completion_cache_for_class(self, obj_class):
206 if self.completion_cache:
207 self.completion_cache.clear_class(obj_class)
208
209 @client._original_only
210 def __enter__(self):
211 self.client.open_session()
212 return self
213
214 @client._original_only
215 def __exit__(self, t, v, tb):
216 self.client.close_session()
217
218 @client._original_only
219 def set_management_url(self, url):
220 self.client.set_management_url(url)
221
222 def get_timings(self):
223 return self.client.get_timings()
224
225 def reset_timings(self):
226 self.client.reset_timings()
227
228 @client._original_only
229 def authenticate(self):
230 """
231 Authenticate against the server.
232
233 Normally this is called automatically when you first access the API,
234 but you can call this method to force authentication right now.
235
236 Returns on success; raises :exc:`exceptions.Unauthorized` if the
237 credentials are wrong.
238 """
239 self.client.authenticate()
diff --git a/novaclient/v2/cloudpipe.py b/novaclient/v2/cloudpipe.py
new file mode 100644
index 0000000..c0926ed
--- /dev/null
+++ b/novaclient/v2/cloudpipe.py
@@ -0,0 +1,61 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Cloudpipe interface."""
17
18from novaclient import base
19
20
21class Cloudpipe(base.Resource):
22 """A cloudpipe instance is a VPN attached to a project's VLAN."""
23
24 def __repr__(self):
25 return "<Cloudpipe: %s>" % self.project_id
26
27 def delete(self):
28 self.manager.delete(self)
29
30
31class CloudpipeManager(base.ManagerWithFind):
32 resource_class = Cloudpipe
33
34 def create(self, project):
35 """
36 Launch a cloudpipe instance.
37
38 :param project: UUID of the project (tenant) for the cloudpipe
39 """
40 body = {'cloudpipe': {'project_id': project}}
41 return self._create('/os-cloudpipe', body, 'instance_id',
42 return_raw=True)
43
44 def list(self):
45 """
46 Get a list of cloudpipe instances.
47 """
48 return self._list('/os-cloudpipe', 'cloudpipes')
49
50 def update(self, address, port):
51 """
52 Update VPN address and port for all networks associated
53 with the project defined by authentication
54
55 :param address: IP address
56 :param port: Port number
57 """
58
59 body = {'configure_project': {'vpn_ip': address,
60 'vpn_port': port}}
61 self._update("/os-cloudpipe/configure-project", body)
diff --git a/novaclient/v2/contrib/__init__.py b/novaclient/v2/contrib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/novaclient/v2/contrib/__init__.py
diff --git a/novaclient/v2/contrib/assisted_volume_snapshots.py b/novaclient/v2/contrib/assisted_volume_snapshots.py
new file mode 100644
index 0000000..ce1a041
--- /dev/null
+++ b/novaclient/v2/contrib/assisted_volume_snapshots.py
@@ -0,0 +1,48 @@
1# Copyright (C) 2013, Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16Assisted volume snapshots - to be used by Cinder and not end users.
17"""
18
19import json
20
21from novaclient import base
22
23
24class Snapshot(base.Resource):
25 def __repr__(self):
26 return "<Snapshot: %s>" % self.id
27
28 def delete(self):
29 """
30 Delete this snapshot.
31 """
32 self.manager.delete(self)
33
34
35class AssistedSnapshotManager(base.Manager):
36 resource_class = Snapshot
37
38 def create(self, volume_id, create_info):
39 body = {'snapshot': {'volume_id': volume_id,
40 'create_info': create_info}}
41 return self._create('/os-assisted-volume-snapshots', body, 'snapshot')
42
43 def delete(self, snapshot, delete_info):
44 self._delete("/os-assisted-volume-snapshots/%s?delete_info=%s" % (
45 base.getid(snapshot), json.dumps(delete_info)))
46
47manager_class = AssistedSnapshotManager
48name = 'assisted_volume_snapshots'
diff --git a/novaclient/v2/contrib/baremetal.py b/novaclient/v2/contrib/baremetal.py
new file mode 100644
index 0000000..d23a38e
--- /dev/null
+++ b/novaclient/v2/contrib/baremetal.py
@@ -0,0 +1,339 @@
1# Copyright 2013 Hewlett-Packard Development Company, L.P.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Baremetal interface (v2 extension).
18"""
19
20from novaclient import base
21from novaclient.i18n import _
22from novaclient.openstack.common import cliutils
23from novaclient import utils
24
25
26class BareMetalNode(base.Resource):
27 """
28 A baremetal node (typically a physical server or an empty VM).
29 """
30
31 def __repr__(self):
32 return "<BareMetalNode: %s>" % self.id
33
34
35class BareMetalNodeInterface(base.Resource):
36 """
37 An interface belonging to a baremetal node.
38 """
39
40 def __repr__(self):
41 return "<BareMetalNodeInterface: %s>" % self.id
42
43
44class BareMetalNodeManager(base.ManagerWithFind):
45 """
46 Manage :class:`BareMetalNode` resources.
47 """
48 resource_class = BareMetalNode
49
50 def create(self,
51 service_host,
52 cpus,
53 memory_mb,
54 local_gb,
55 prov_mac_address,
56 pm_address=None,
57 pm_user=None,
58 pm_password=None,
59 terminal_port=None):
60 """
61 Create a baremetal node.
62
63 :param service_host: Name of controlling compute host
64 :param cpus: Number of CPUs in the node
65 :param memory_mb: Megabytes of RAM in the node
66 :param local_gb: Gigabytes of local storage in the node
67 :param pm_address: Power management IP for the node
68 :param pm_user: Username for the node's power management
69 :param pm_password: Password for the node's power management
70 :param prov_mac_address: MAC address to provision the node
71 :param terminal_port: ShellInABox port
72 :rtype: :class:`BareMetalNode`
73 """
74 body = {'node': {'service_host': service_host,
75 'cpus': cpus,
76 'memory_mb': memory_mb,
77 'local_gb': local_gb,
78 'pm_address': pm_address,
79 'pm_user': pm_user,
80 'pm_password': pm_password,
81 'prov_mac_address': prov_mac_address,
82 'terminal_port': terminal_port}}
83
84 return self._create('/os-baremetal-nodes', body, 'node')
85
86 def delete(self, node):
87 """
88 Delete a baremetal node.
89
90 :param node: The :class:`BareMetalNode` to delete.
91 """
92 self._delete('/os-baremetal-nodes/%s' % base.getid(node))
93
94 def get(self, node_id):
95 """
96 Get a baremetal node.
97
98 :param node_id: The ID of the node to delete.
99 :rtype: :class:`BareMetalNode`
100 """
101 return self._get("/os-baremetal-nodes/%s" % node_id, 'node')
102
103 def list(self):
104 """
105 Get a list of all baremetal nodes.
106
107 :rtype: list of :class:`BareMetalNode`
108 """
109 return self._list('/os-baremetal-nodes', 'nodes')
110
111 def add_interface(self, node_id, address, datapath_id=0, port_no=0):
112 """
113 Add an interface to a baremetal node.
114
115 :param node_id: The ID of the node to modify.
116 :param address: The MAC address to add.
117 :param datapath_id: Datapath ID of OpenFlow switch for the interface
118 :param port_no: OpenFlow port number for the interface
119 :rtype: :class:`BareMetalNodeInterface`
120 """
121 body = {'add_interface': {'address': address,
122 'datapath_id': datapath_id,
123 'port_no': port_no}}
124 url = '/os-baremetal-nodes/%s/action' % node_id
125 _resp, body = self.api.client.post(url, body=body)
126 return BareMetalNodeInterface(self, body['interface'])
127
128 def remove_interface(self, node_id, address):
129 """
130 Remove an interface from a baremetal node.
131
132 :param node_id: The ID of the node to modify.
133 :param address: The MAC address to remove.
134 :rtype: bool
135 """
136 req_body = {'remove_interface': {'address': address}}
137 url = '/os-baremetal-nodes/%s/action' % node_id
138 self.api.client.post(url, body=req_body)
139
140 def list_interfaces(self, node_id):
141 """
142 List the interfaces on a baremetal node.
143
144 :param node_id: The ID of the node to list.
145 :rtype: list
146 """
147 interfaces = []
148 node = self._get("/os-baremetal-nodes/%s" % node_id, 'node')
149 for interface in node.interfaces:
150 interface_object = BareMetalNodeInterface(self, interface)
151 interfaces.append(interface_object)
152 return interfaces
153
154
155@cliutils.arg(
156 'service_host',
157 metavar='<service_host>',
158 help=_('Name of nova compute host which will control this baremetal '
159 'node'))
160@cliutils.arg(
161 'cpus',
162 metavar='<cpus>',
163 type=int,
164 help=_('Number of CPUs in the node'))
165@cliutils.arg(
166 'memory_mb',
167 metavar='<memory_mb>',
168 type=int,
169 help=_('Megabytes of RAM in the node'))
170@cliutils.arg(
171 'local_gb',
172 metavar='<local_gb>',
173 type=int,
174 help=_('Gigabytes of local storage in the node'))
175@cliutils.arg(
176 'prov_mac_address',
177 metavar='<prov_mac_address>',
178 help=_('MAC address to provision the node'))
179@cliutils.arg(
180 '--pm_address', default=None,
181 metavar='<pm_address>',
182 help=_('Power management IP for the node'))
183@cliutils.arg(
184 '--pm_user', default=None,
185 metavar='<pm_user>',
186 help=_('Username for the node\'s power management'))
187@cliutils.arg(
188 '--pm_password', default=None,
189 metavar='<pm_password>',
190 help=_('Password for the node\'s power management'))
191@cliutils.arg(
192 '--terminal_port', default=None,
193 metavar='<terminal_port>',
194 type=int,
195 help=_('ShellInABox port?'))
196def do_baremetal_node_create(cs, args):
197 """Create a baremetal node."""
198 node = cs.baremetal.create(args.service_host, args.cpus,
199 args.memory_mb, args.local_gb,
200 args.prov_mac_address,
201 pm_address=args.pm_address,
202 pm_user=args.pm_user,
203 pm_password=args.pm_password,
204 terminal_port=args.terminal_port)
205 _print_baremetal_resource(node)
206
207
208@cliutils.arg(
209 'node',
210 metavar='<node>',
211 help=_('ID of the node to delete.'))
212def do_baremetal_node_delete(cs, args):
213 """Remove a baremetal node and any associated interfaces."""
214 node = _find_baremetal_node(cs, args.node)
215 cs.baremetal.delete(node)
216
217
218def _translate_baremetal_node_keys(collection):
219 convert = [('service_host', 'host'),
220 ('local_gb', 'disk_gb'),
221 ('prov_mac_address', 'mac_address'),
222 ('pm_address', 'pm_address'),
223 ('pm_user', 'pm_username'),
224 ('pm_password', 'pm_password'),
225 ('terminal_port', 'terminal_port'),
226 ]
227 for item in collection:
228 keys = item.__dict__.keys()
229 for from_key, to_key in convert:
230 if from_key in keys and to_key not in keys:
231 setattr(item, to_key, item._info[from_key])
232
233
234def _print_baremetal_nodes_list(nodes):
235 """Print the list of baremetal nodes."""
236
237 def _parse_address(fields):
238 macs = []
239 for interface in fields.interfaces:
240 macs.append(interface['address'])
241 return ', '.join("%s" % i for i in macs)
242
243 formatters = {
244 'MAC Address': _parse_address
245 }
246
247 _translate_baremetal_node_keys(nodes)
248 utils.print_list(nodes, [
249 'ID',
250 'Host',
251 'Task State',
252 'CPUs',
253 'Memory_MB',
254 'Disk_GB',
255 'MAC Address',
256 'PM Address',
257 'PM Username',
258 'PM Password',
259 'Terminal Port',
260 ], formatters=formatters)
261
262
263def do_baremetal_node_list(cs, _args):
264 """Print list of available baremetal nodes."""
265 nodes = cs.baremetal.list()
266 _print_baremetal_nodes_list(nodes)
267
268
269def _find_baremetal_node(cs, node):
270 """Get a node by ID."""
271 return utils.find_resource(cs.baremetal, node)
272
273
274def _print_baremetal_resource(resource):
275 """Print details of a baremetal resource."""
276 info = resource._info.copy()
277 utils.print_dict(info)
278
279
280def _print_baremetal_node_interfaces(interfaces):
281 """Print interfaces of a baremetal node."""
282 utils.print_list(interfaces, [
283 'ID',
284 'Datapath_ID',
285 'Port_No',
286 'Address',
287 ])
288
289
290@cliutils.arg(
291 'node',
292 metavar='<node>',
293 help=_("ID of node"))
294def do_baremetal_node_show(cs, args):
295 """Show information about a baremetal node."""
296 node = _find_baremetal_node(cs, args.node)
297 _print_baremetal_resource(node)
298
299
300@cliutils.arg(
301 'node',
302 metavar='<node>',
303 help=_("ID of node"))
304@cliutils.arg(
305 'address',
306 metavar='<address>',
307 help=_("MAC address of interface"))
308@cliutils.arg(
309 '--datapath_id',
310 default=0,
311 metavar='<datapath_id>',
312 help=_("OpenFlow Datapath ID of interface"))
313@cliutils.arg(
314 '--port_no',
315 default=0,
316 metavar='<port_no>',
317 help=_("OpenFlow port number of interface"))
318def do_baremetal_interface_add(cs, args):
319 """Add a network interface to a baremetal node."""
320 bmif = cs.baremetal.add_interface(args.node, args.address,
321 args.datapath_id, args.port_no)
322 _print_baremetal_resource(bmif)
323
324
325@cliutils.arg('node', metavar='<node>', help=_("ID of node"))
326@cliutils.arg(
327 'address',
328 metavar='<address>',
329 help=_("MAC address of interface"))
330def do_baremetal_interface_remove(cs, args):
331 """Remove a network interface from a baremetal node."""
332 cs.baremetal.remove_interface(args.node, args.address)
333
334
335@cliutils.arg('node', metavar='<node>', help=_("ID of node"))
336def do_baremetal_interface_list(cs, args):
337 """List network interfaces associated with a baremetal node."""
338 interfaces = cs.baremetal.list_interfaces(args.node)
339 _print_baremetal_node_interfaces(interfaces)
diff --git a/novaclient/v2/contrib/cells.py b/novaclient/v2/contrib/cells.py
new file mode 100644
index 0000000..bfc6893
--- /dev/null
+++ b/novaclient/v2/contrib/cells.py
@@ -0,0 +1,74 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import base
17from novaclient.i18n import _
18from novaclient.openstack.common import cliutils
19from novaclient import utils
20
21
22class Cell(base.Resource):
23 def __repr__(self):
24 return "<Cell: %s>" % self.name
25
26
27class CellsManager(base.Manager):
28 resource_class = Cell
29
30 def get(self, cell_name):
31 """
32 Get a cell.
33
34 :param cell: Name of the :class:`Cell` to get.
35 :rtype: :class:`Cell`
36 """
37 return self._get("/os-cells/%s" % cell_name, "cell")
38
39 def capacities(self, cell_name=None):
40 """
41 Get capacities for a cell.
42
43 :param cell: Name of the :class:`Cell` to get capacities for.
44 :rtype: :class:`Cell`
45 """
46 path = ["%s/capacities" % cell_name, "capacities"][cell_name is None]
47 return self._get("/os-cells/%s" % path, "cell")
48
49
50@cliutils.arg(
51 'cell',
52 metavar='<cell-name>',
53 help=_('Name of the cell.'))
54def do_cell_show(cs, args):
55 """Show details of a given cell."""
56 cell = cs.cells.get(args.cell)
57 utils.print_dict(cell._info)
58
59
60@cliutils.arg(
61 '--cell',
62 metavar='<cell-name>',
63 help=_("Name of the cell to get the capacities."),
64 default=None)
65def do_cell_capacities(cs, args):
66 """Get cell capacities for all cells or a given cell."""
67 cell = cs.cells.capacities(args.cell)
68 print(_("Ram Available: %s MB") % cell.capacities['ram_free']['total_mb'])
69 utils.print_dict(cell.capacities['ram_free']['units_by_mb'],
70 dict_property='Ram(MB)', dict_value="Units")
71 print(_("\nDisk Available: %s MB") %
72 cell.capacities['disk_free']['total_mb'])
73 utils.print_dict(cell.capacities['disk_free']['units_by_mb'],
74 dict_property='Disk(MB)', dict_value="Units")
diff --git a/novaclient/v2/contrib/deferred_delete.py b/novaclient/v2/contrib/deferred_delete.py
new file mode 100644
index 0000000..5d8d7d9
--- /dev/null
+++ b/novaclient/v2/contrib/deferred_delete.py
@@ -0,0 +1,28 @@
1# Copyright 2013 OpenStack Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from novaclient.openstack.common import cliutils
16from novaclient import utils
17
18
19@cliutils.arg('server', metavar='<server>', help='Name or ID of server.')
20def do_force_delete(cs, args):
21 """Force delete a server."""
22 utils.find_resource(cs.servers, args.server).force_delete()
23
24
25@cliutils.arg('server', metavar='<server>', help='Name or ID of server.')
26def do_restore(cs, args):
27 """Restore a soft-deleted server."""
28 utils.find_resource(cs.servers, args.server).restore()
diff --git a/novaclient/v2/contrib/host_evacuate.py b/novaclient/v2/contrib/host_evacuate.py
new file mode 100644
index 0000000..b08e28c
--- /dev/null
+++ b/novaclient/v2/contrib/host_evacuate.py
@@ -0,0 +1,64 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import base
17from novaclient.i18n import _
18from novaclient.openstack.common import cliutils
19from novaclient import utils
20
21
22class EvacuateHostResponse(base.Resource):
23 pass
24
25
26def _server_evacuate(cs, server, args):
27 success = True
28 error_message = ""
29 try:
30 cs.servers.evacuate(server=server['uuid'], host=args.target_host,
31 on_shared_storage=args.on_shared_storage)
32 except Exception as e:
33 success = False
34 error_message = _("Error while evacuating instance: %s") % e
35 return EvacuateHostResponse(base.Manager,
36 {"server_uuid": server['uuid'],
37 "evacuate_accepted": success,
38 "error_message": error_message})
39
40
41@cliutils.arg('host', metavar='<host>', help='Name of host.')
42@cliutils.arg(
43 '--target_host',
44 metavar='<target_host>',
45 default=None,
46 help=_('Name of target host. If no host is specified the scheduler will '
47 'select a target.'))
48@cliutils.arg(
49 '--on-shared-storage',
50 dest='on_shared_storage',
51 action="store_true",
52 default=False,
53 help=_('Specifies whether all instances files are on shared storage'))
54def do_host_evacuate(cs, args):
55 """Evacuate all instances from failed host."""
56 hypervisors = cs.hypervisors.search(args.host, servers=True)
57 response = []
58 for hyper in hypervisors:
59 if hasattr(hyper, 'servers'):
60 for server in hyper.servers:
61 response.append(_server_evacuate(cs, server, args))
62
63 utils.print_list(response,
64 ["Server UUID", "Evacuate Accepted", "Error Message"])
diff --git a/novaclient/v2/contrib/host_evacuate_live.py b/novaclient/v2/contrib/host_evacuate_live.py
new file mode 100644
index 0000000..276fb2f
--- /dev/null
+++ b/novaclient/v2/contrib/host_evacuate_live.py
@@ -0,0 +1,68 @@
1# Copyright 2014 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient.i18n import _
17from novaclient.openstack.common import cliutils
18from novaclient import utils
19
20
21def _server_live_migrate(cs, server, args):
22 class HostEvacuateLiveResponse(object):
23 def __init__(self, server_uuid, live_migration_accepted,
24 error_message):
25 self.server_uuid = server_uuid
26 self.live_migration_accepted = live_migration_accepted
27 self.error_message = error_message
28 success = True
29 error_message = ""
30 try:
31 cs.servers.live_migrate(server['uuid'], args.target_host,
32 args.block_migrate, args.disk_over_commit)
33 except Exception as e:
34 success = False
35 error_message = _("Error while live migrating instance: %s") % e
36 return HostEvacuateLiveResponse(server['uuid'],
37 success,
38 error_message)
39
40
41@cliutils.arg('host', metavar='<host>', help='Name of host.')
42@cliutils.arg(
43 '--target-host',
44 metavar='<target_host>',
45 default=None,
46 help=_('Name of target host.'))
47@cliutils.arg(
48 '--block-migrate',
49 action='store_true',
50 default=False,
51 help=_('Enable block migration.'))
52@cliutils.arg(
53 '--disk-over-commit',
54 action='store_true',
55 default=False,
56 help=_('Enable disk overcommit.'))
57def do_host_evacuate_live(cs, args):
58 """Live migrate all instances of the specified host
59 to other available hosts.
60 """
61 hypervisors = cs.hypervisors.search(args.host, servers=True)
62 response = []
63 for hyper in hypervisors:
64 for server in getattr(hyper, 'servers', []):
65 response.append(_server_live_migrate(cs, server, args))
66
67 utils.print_list(response, ["Server UUID", "Live Migration Accepted",
68 "Error Message"])
diff --git a/novaclient/v2/contrib/host_servers_migrate.py b/novaclient/v2/contrib/host_servers_migrate.py
new file mode 100644
index 0000000..470f161
--- /dev/null
+++ b/novaclient/v2/contrib/host_servers_migrate.py
@@ -0,0 +1,51 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import base
17from novaclient.i18n import _
18from novaclient.openstack.common import cliutils
19from novaclient import utils
20
21
22class HostServersMigrateResponse(base.Resource):
23 pass
24
25
26def _server_migrate(cs, server):
27 success = True
28 error_message = ""
29 try:
30 cs.servers.migrate(server['uuid'])
31 except Exception as e:
32 success = False
33 error_message = _("Error while migrating instance: %s") % e
34 return HostServersMigrateResponse(base.Manager,
35 {"server_uuid": server['uuid'],
36 "migration_accepted": success,
37 "error_message": error_message})
38
39
40@cliutils.arg('host', metavar='<host>', help='Name of host.')
41def do_host_servers_migrate(cs, args):
42 """Migrate all instances of the specified host to other available hosts."""
43 hypervisors = cs.hypervisors.search(args.host, servers=True)
44 response = []
45 for hyper in hypervisors:
46 if hasattr(hyper, 'servers'):
47 for server in hyper.servers:
48 response.append(_server_migrate(cs, server))
49
50 utils.print_list(response,
51 ["Server UUID", "Migration Accepted", "Error Message"])
diff --git a/novaclient/v2/contrib/instance_action.py b/novaclient/v2/contrib/instance_action.py
new file mode 100644
index 0000000..10e518e
--- /dev/null
+++ b/novaclient/v2/contrib/instance_action.py
@@ -0,0 +1,72 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16import pprint
17
18from novaclient import base
19from novaclient.i18n import _
20from novaclient.openstack.common import cliutils
21from novaclient import utils
22
23
24class InstanceActionManager(base.ManagerWithFind):
25 resource_class = base.Resource
26
27 def get(self, server, request_id):
28 """
29 Get details of an action performed on an instance.
30
31 :param request_id: The request_id of the action to get.
32 """
33 return self._get("/servers/%s/os-instance-actions/%s" %
34 (base.getid(server), request_id), 'instanceAction')
35
36 def list(self, server):
37 """
38 Get a list of actions performed on an server.
39 """
40 return self._list('/servers/%s/os-instance-actions' %
41 base.getid(server), 'instanceActions')
42
43
44@cliutils.arg(
45 'server',
46 metavar='<server>',
47 help=_('Name or UUID of the server to show an action for.'))
48@cliutils.arg(
49 'request_id',
50 metavar='<request_id>',
51 help=_('Request ID of the action to get.'))
52def do_instance_action(cs, args):
53 """Show an action."""
54 server = utils.find_resource(cs.servers, args.server)
55 action_resource = cs.instance_action.get(server, args.request_id)
56 action = action_resource._info
57 if 'events' in action:
58 action['events'] = pprint.pformat(action['events'])
59 utils.print_dict(action)
60
61
62@cliutils.arg(
63 'server',
64 metavar='<server>',
65 help=_('Name or UUID of the server to list actions for.'))
66def do_instance_action_list(cs, args):
67 """List actions on a server."""
68 server = utils.find_resource(cs.servers, args.server)
69 actions = cs.instance_action.list(server)
70 utils.print_list(actions,
71 ['Action', 'Request_ID', 'Message', 'Start_Time'],
72 sortby_index=3)
diff --git a/novaclient/v2/contrib/list_extensions.py b/novaclient/v2/contrib/list_extensions.py
new file mode 100644
index 0000000..7eb9f16
--- /dev/null
+++ b/novaclient/v2/contrib/list_extensions.py
@@ -0,0 +1,46 @@
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import base
17from novaclient import utils
18
19
20class ListExtResource(base.Resource):
21 @property
22 def summary(self):
23 descr = self.description.strip()
24 if not descr:
25 return '??'
26 lines = descr.split("\n")
27 if len(lines) == 1:
28 return lines[0]
29 else:
30 return lines[0] + "..."
31
32
33class ListExtManager(base.Manager):
34 resource_class = ListExtResource
35
36 def show_all(self):
37 return self._list("/extensions", 'extensions')
38
39
40def do_list_extensions(client, _args):
41 """
42 List all the os-api extensions that are available.
43 """
44 extensions = client.list_extensions.show_all()
45 fields = ["Name", "Summary", "Alias", "Updated"]
46 utils.print_list(extensions, fields)
diff --git a/novaclient/v2/contrib/metadata_extensions.py b/novaclient/v2/contrib/metadata_extensions.py
new file mode 100644
index 0000000..ad843b7
--- /dev/null
+++ b/novaclient/v2/contrib/metadata_extensions.py
@@ -0,0 +1,47 @@
1# Copyright 2013 Rackspace Hosting
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient.i18n import _
17from novaclient.openstack.common import cliutils
18from novaclient.v2 import shell
19
20
21@cliutils.arg(
22 'host',
23 metavar='<host>',
24 help=_('Name of host.'))
25@cliutils.arg(
26 'action',
27 metavar='<action>',
28 choices=['set', 'delete'],
29 help=_("Actions: 'set' or 'delete'"))
30@cliutils.arg(
31 'metadata',
32 metavar='<key=value>',
33 nargs='+',
34 action='append',
35 default=[],
36 help=_('Metadata to set or delete (only key is necessary on delete)'))
37def do_host_meta(cs, args):
38 """Set or Delete metadata on all instances of a host."""
39 hypervisors = cs.hypervisors.search(args.host, servers=True)
40 for hyper in hypervisors:
41 metadata = shell._extract_metadata(args)
42 if hasattr(hyper, 'servers'):
43 for server in hyper.servers:
44 if args.action == 'set':
45 cs.servers.set_meta(server['uuid'], metadata)
46 elif args.action == 'delete':
47 cs.servers.delete_meta(server['uuid'], metadata.keys())
diff --git a/novaclient/v2/contrib/migrations.py b/novaclient/v2/contrib/migrations.py
new file mode 100644
index 0000000..1595981
--- /dev/null
+++ b/novaclient/v2/contrib/migrations.py
@@ -0,0 +1,91 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13"""
14migration interface
15"""
16
17from six.moves.urllib import parse
18
19from novaclient import base
20from novaclient.i18n import _
21from novaclient.openstack.common import cliutils
22from novaclient import utils
23
24
25class Migration(base.Resource):
26 def __repr__(self):
27 return "<Migration: %s>" % self.id
28
29
30class MigrationManager(base.ManagerWithFind):
31 resource_class = Migration
32
33 def list(self, host=None, status=None, cell_name=None):
34 """
35 Get a list of migrations.
36 :param host: (optional) filter migrations by host name.
37 :param status: (optional) filter migrations by status.
38 :param cell_name: (optional) filter migrations for a cell.
39 """
40 opts = {}
41 if host:
42 opts['host'] = host
43 if status:
44 opts['status'] = status
45 if cell_name:
46 opts['cell_name'] = cell_name
47
48 # Transform the dict to a sequence of two-element tuples in fixed
49 # order, then the encoded string will be consistent in Python 2&3.
50 new_opts = sorted(opts.items(), key=lambda x: x[0])
51
52 query_string = "?%s" % parse.urlencode(new_opts) if new_opts else ""
53
54 return self._list("/os-migrations%s" % query_string, "migrations")
55
56
57@cliutils.arg(
58 '--host',
59 dest='host',
60 metavar='<host>',
61 help=_('Fetch migrations for the given host.'))
62@cliutils.arg(
63 '--status',
64 dest='status',
65 metavar='<status>',
66 help=_('Fetch migrations for the given status.'))
67@cliutils.arg(
68 '--cell_name',
69 dest='cell_name',
70 metavar='<cell_name>',
71 help=_('Fetch migrations for the given cell_name.'))
72def do_migration_list(cs, args):
73 """Print a list of migrations."""
74 _print_migrations(cs.migrations.list(args.host, args.status,
75 args.cell_name))
76
77
78def _print_migrations(migrations):
79 fields = ['Source Node', 'Dest Node', 'Source Compute', 'Dest Compute',
80 'Dest Host', 'Status', 'Instance UUID', 'Old Flavor',
81 'New Flavor', 'Created At', 'Updated At']
82
83 def old_flavor(migration):
84 return migration.old_instance_type_id
85
86 def new_flavor(migration):
87 return migration.new_instance_type_id
88
89 formatters = {'Old Flavor': old_flavor, 'New Flavor': new_flavor}
90
91 utils.print_list(migrations, fields, formatters)
diff --git a/novaclient/v2/contrib/server_external_events.py b/novaclient/v2/contrib/server_external_events.py
new file mode 100644
index 0000000..a45914b
--- /dev/null
+++ b/novaclient/v2/contrib/server_external_events.py
@@ -0,0 +1,43 @@
1# Copyright (C) 2014, Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16External event triggering for servers, not to be used by users.
17"""
18
19from novaclient import base
20
21
22class Event(base.Resource):
23 def __repr__(self):
24 return "<Event: %s>" % self.name
25
26
27class ServerExternalEventManager(base.Manager):
28 resource_class = Event
29
30 def create(self, events):
31 """Create one or more server events.
32
33 :param:events: A list of dictionaries containing 'server_uuid', 'name',
34 'status', and 'tag' (which may be absent)
35 """
36
37 body = {'events': events}
38 return self._create('/os-server-external-events', body, 'events',
39 return_raw=True)
40
41
42manager_class = ServerExternalEventManager
43name = 'server_external_events'
diff --git a/novaclient/v2/contrib/tenant_networks.py b/novaclient/v2/contrib/tenant_networks.py
new file mode 100644
index 0000000..06edeb1
--- /dev/null
+++ b/novaclient/v2/contrib/tenant_networks.py
@@ -0,0 +1,82 @@
1# Copyright 2013 OpenStack Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from novaclient import base
16from novaclient.i18n import _
17from novaclient.openstack.common import cliutils
18from novaclient import utils
19
20
21class TenantNetwork(base.Resource):
22 def delete(self):
23 self.manager.delete(network=self)
24
25
26class TenantNetworkManager(base.ManagerWithFind):
27 resource_class = base.Resource
28
29 def list(self):
30 return self._list('/os-tenant-networks', 'networks')
31
32 def get(self, network):
33 return self._get('/os-tenant-networks/%s' % base.getid(network),
34 'network')
35
36 def delete(self, network):
37 self._delete('/os-tenant-networks/%s' % base.getid(network))
38
39 def create(self, label, cidr):
40 body = {'network': {'label': label, 'cidr': cidr}}
41 return self._create('/os-tenant-networks', body, 'network')
42
43
44@cliutils.arg('network_id', metavar='<network_id>', help='ID of network')
45def do_net(cs, args):
46 """
47 Show a network
48 """
49 network = cs.tenant_networks.get(args.network_id)
50 utils.print_dict(network._info)
51
52
53def do_net_list(cs, args):
54 """
55 List networks
56 """
57 networks = cs.tenant_networks.list()
58 utils.print_list(networks, ['ID', 'Label', 'CIDR'])
59
60
61@cliutils.arg(
62 'label',
63 metavar='<network_label>',
64 help=_('Network label (ex. my_new_network)'))
65@cliutils.arg(
66 'cidr',
67 metavar='<cidr>',
68 help=_('IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)'))
69def do_net_create(cs, args):
70 """
71 Create a network
72 """
73 network = cs.tenant_networks.create(args.label, args.cidr)
74 utils.print_dict(network._info)
75
76
77@cliutils.arg('network_id', metavar='<network_id>', help='ID of network')
78def do_net_delete(cs, args):
79 """
80 Delete a network
81 """
82 cs.tenant_networks.delete(args.network_id)
diff --git a/novaclient/v2/fixed_ips.py b/novaclient/v2/fixed_ips.py
new file mode 100644
index 0000000..4e7c0e9
--- /dev/null
+++ b/novaclient/v2/fixed_ips.py
@@ -0,0 +1,56 @@
1# Copyright 2012 IBM Corp.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Fixed IPs interface.
18"""
19
20from novaclient import base
21
22
23class FixedIP(base.Resource):
24 def __repr__(self):
25 return "<FixedIP: %s>" % self.address
26
27
28class FixedIPsManager(base.Manager):
29 resource_class = FixedIP
30
31 def get(self, fixed_ip):
32 """
33 Show information for a Fixed IP
34
35 :param fixed_ip: Fixed IP address to get info for
36 """
37 return self._get('/os-fixed-ips/%s' % base.getid(fixed_ip),
38 "fixed_ip")
39
40 def reserve(self, fixed_ip):
41 """Reserve a Fixed IP
42
43 :param fixed_ip: Fixed IP address to reserve
44 """
45 body = {"reserve": None}
46 self.api.client.post('/os-fixed-ips/%s/action' % base.getid(fixed_ip),
47 body=body)
48
49 def unreserve(self, fixed_ip):
50 """Unreserve a Fixed IP
51
52 :param fixed_ip: Fixed IP address to unreserve
53 """
54 body = {"unreserve": None}
55 self.api.client.post('/os-fixed-ips/%s/action' % base.getid(fixed_ip),
56 body=body)
diff --git a/novaclient/v2/flavor_access.py b/novaclient/v2/flavor_access.py
new file mode 100644
index 0000000..ca78bdf
--- /dev/null
+++ b/novaclient/v2/flavor_access.py
@@ -0,0 +1,70 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Flavor access interface."""
17
18from novaclient import base
19from novaclient.i18n import _
20
21
22class FlavorAccess(base.Resource):
23 def __repr__(self):
24 return ("<FlavorAccess flavor id: %s, tenant id: %s>" %
25 (self.flavor_id, self.tenant_id))
26
27
28class FlavorAccessManager(base.ManagerWithFind):
29 """
30 Manage :class:`FlavorAccess` resources.
31 """
32 resource_class = FlavorAccess
33
34 def list(self, **kwargs):
35 if kwargs.get('flavor'):
36 return self._list_by_flavor(kwargs['flavor'])
37 elif kwargs.get('tenant'):
38 return self._list_by_tenant(kwargs['tenant'])
39 else:
40 raise NotImplementedError(_('Unknown list options.'))
41
42 def _list_by_flavor(self, flavor):
43 return self._list('/flavors/%s/os-flavor-access' % base.getid(flavor),
44 'flavor_access')
45
46 def _list_by_tenant(self, tenant):
47 """Print flavor list shared with the given tenant."""
48 # TODO(uni): need to figure out a proper URI for list_by_tenant
49 # since current API already provided current tenant_id information
50 raise NotImplementedError(_('Sorry, query by tenant not supported.'))
51
52 def add_tenant_access(self, flavor, tenant):
53 """Add a tenant to the given flavor access list."""
54 info = {'tenant': tenant}
55 return self._action('addTenantAccess', flavor, info)
56
57 def remove_tenant_access(self, flavor, tenant):
58 """Remove a tenant from the given flavor access list."""
59 info = {'tenant': tenant}
60 return self._action('removeTenantAccess', flavor, info)
61
62 def _action(self, action, flavor, info, **kwargs):
63 """Perform a flavor action."""
64 body = {action: info}
65 self.run_hooks('modify_body_for_action', body, **kwargs)
66 url = '/flavors/%s/action' % base.getid(flavor)
67 _resp, body = self.api.client.post(url, body=body)
68
69 return [self.resource_class(self, res)
70 for res in body['flavor_access']]
diff --git a/novaclient/v2/flavors.py b/novaclient/v2/flavors.py
new file mode 100644
index 0000000..0545ad6
--- /dev/null
+++ b/novaclient/v2/flavors.py
@@ -0,0 +1,207 @@
1# Copyright 2010 Jacob Kaplan-Moss
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16Flavor interface.
17"""
18
19from oslo.utils import strutils
20from six.moves.urllib import parse
21
22from novaclient import base
23from novaclient import exceptions
24from novaclient.i18n import _
25from novaclient import utils
26
27
28class Flavor(base.Resource):
29 """
30 A flavor is an available hardware configuration for a server.
31 """
32 HUMAN_ID = True
33
34 def __repr__(self):
35 return "<Flavor: %s>" % self.name
36
37 @property
38 def ephemeral(self):
39 """
40 Provide a user-friendly accessor to OS-FLV-EXT-DATA:ephemeral
41 """
42 return self._info.get("OS-FLV-EXT-DATA:ephemeral", 'N/A')
43
44 @property
45 def is_public(self):
46 """
47 Provide a user-friendly accessor to os-flavor-access:is_public
48 """
49 return self._info.get("os-flavor-access:is_public", 'N/A')
50
51 def get_keys(self):
52 """
53 Get extra specs from a flavor.
54
55 :param flavor: The :class:`Flavor` to get extra specs from
56 """
57 _resp, body = self.manager.api.client.get(
58 "/flavors/%s/os-extra_specs" % base.getid(self))
59 return body["extra_specs"]
60
61 def set_keys(self, metadata):
62 """
63 Set extra specs on a flavor.
64
65 :param flavor: The :class:`Flavor` to set extra spec on
66 :param metadata: A dict of key/value pairs to be set
67 """
68 utils.validate_flavor_metadata_keys(metadata.keys())
69
70 body = {'extra_specs': metadata}
71 return self.manager._create(
72 "/flavors/%s/os-extra_specs" % base.getid(self), body,
73 "extra_specs", return_raw=True)
74
75 def unset_keys(self, keys):
76 """
77 Unset extra specs on a flavor.
78
79 :param flavor: The :class:`Flavor` to unset extra spec on
80 :param keys: A list of keys to be unset
81 """
82 for k in keys:
83 self.manager._delete(
84 "/flavors/%s/os-extra_specs/%s" % (base.getid(self), k))
85
86 def delete(self):
87 """
88 Delete this flavor.
89 """
90 self.manager.delete(self)
91
92
93class FlavorManager(base.ManagerWithFind):
94 """
95 Manage :class:`Flavor` resources.
96 """
97 resource_class = Flavor
98 is_alphanum_id_allowed = True
99
100 def list(self, detailed=True, is_public=True):
101 """
102 Get a list of all flavors.
103
104 :rtype: list of :class:`Flavor`.
105 """
106 qparams = {}
107 # is_public is ternary - None means give all flavors.
108 # By default Nova assumes True and gives admins public flavors
109 # and flavors from their own projects only.
110 if not is_public:
111 qparams['is_public'] = is_public
112 query_string = "?%s" % parse.urlencode(qparams) if qparams else ""
113
114 detail = ""
115 if detailed:
116 detail = "/detail"
117
118 return self._list("/flavors%s%s" % (detail, query_string), "flavors")
119
120 def get(self, flavor):
121 """
122 Get a specific flavor.
123
124 :param flavor: The ID of the :class:`Flavor` to get.
125 :rtype: :class:`Flavor`
126 """
127 return self._get("/flavors/%s" % base.getid(flavor), "flavor")
128
129 def delete(self, flavor):
130 """
131 Delete a specific flavor.
132
133 :param flavor: The ID of the :class:`Flavor` to get.
134 """
135 self._delete("/flavors/%s" % base.getid(flavor))
136
137 def _build_body(self, name, ram, vcpus, disk, id, swap,
138 ephemeral, rxtx_factor, is_public):
139 return {
140 "flavor": {
141 "name": name,
142 "ram": ram,
143 "vcpus": vcpus,
144 "disk": disk,
145 "id": id,
146 "swap": swap,
147 "OS-FLV-EXT-DATA:ephemeral": ephemeral,
148 "rxtx_factor": rxtx_factor,
149 "os-flavor-access:is_public": is_public,
150 }
151 }
152
153 def create(self, name, ram, vcpus, disk, flavorid="auto",
154 ephemeral=0, swap=0, rxtx_factor=1.0, is_public=True):
155 """
156 Create a flavor.
157
158 :param name: Descriptive name of the flavor
159 :param ram: Memory in MB for the flavor
160 :param vcpus: Number of VCPUs for the flavor
161 :param disk: Size of local disk in GB
162 :param flavorid: ID for the flavor (optional). You can use the reserved
163 value ``"auto"`` to have Nova generate a UUID for the
164 flavor in cases where you cannot simply pass ``None``.
165 :param swap: Swap space in MB
166 :param rxtx_factor: RX/TX factor
167 :rtype: :class:`Flavor`
168 """
169
170 try:
171 ram = int(ram)
172 except (TypeError, ValueError):
173 raise exceptions.CommandError(_("Ram must be an integer."))
174 try:
175 vcpus = int(vcpus)
176 except (TypeError, ValueError):
177 raise exceptions.CommandError(_("VCPUs must be an integer."))
178 try:
179 disk = int(disk)
180 except (TypeError, ValueError):
181 raise exceptions.CommandError(_("Disk must be an integer."))
182
183 if flavorid == "auto":
184 flavorid = None
185
186 try:
187 swap = int(swap)
188 except (TypeError, ValueError):
189 raise exceptions.CommandError(_("Swap must be an integer."))
190 try:
191 ephemeral = int(ephemeral)
192 except (TypeError, ValueError):
193 raise exceptions.CommandError(_("Ephemeral must be an integer."))
194 try:
195 rxtx_factor = float(rxtx_factor)
196 except (TypeError, ValueError):
197 raise exceptions.CommandError(_("rxtx_factor must be a float."))
198
199 try:
200 is_public = strutils.bool_from_string(is_public, True)
201 except Exception:
202 raise exceptions.CommandError(_("is_public must be a boolean."))
203
204 body = self._build_body(name, ram, vcpus, disk, flavorid, swap,
205 ephemeral, rxtx_factor, is_public)
206
207 return self._create("/flavors", body, "flavor")
diff --git a/novaclient/v2/floating_ip_dns.py b/novaclient/v2/floating_ip_dns.py
new file mode 100644
index 0000000..41df0f6
--- /dev/null
+++ b/novaclient/v2/floating_ip_dns.py
@@ -0,0 +1,121 @@
1# Copyright 2011 Andrew Bogott for The Wikimedia Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from six.moves.urllib import parse
17
18from novaclient import base
19
20
21def _quote_domain(domain):
22 """Special quoting rule for placing domain names on a url line.
23
24 Domain names tend to have .'s in them. Urllib doesn't quote dots,
25 but Routes tends to choke on them, so we need an extra level of
26 by-hand quoting here.
27 """
28 return parse.quote(domain.replace('.', '%2E'))
29
30
31class FloatingIPDNSDomain(base.Resource):
32 def delete(self):
33 self.manager.delete(self.domain)
34
35 def create(self):
36 if self.scope == 'public':
37 self.manager.create_public(self.domain, self.project)
38 else:
39 self.manager.create_private(self.domain, self.availability_zone)
40
41 def get(self):
42 entries = self.manager.domains()
43 for entry in entries:
44 if entry.get('domain') == self.domain:
45 return entry
46
47 return None
48
49
50class FloatingIPDNSDomainManager(base.Manager):
51 resource_class = FloatingIPDNSDomain
52
53 def domains(self):
54 """Return the list of available dns domains."""
55 return self._list("/os-floating-ip-dns", "domain_entries")
56
57 def create_private(self, fqdomain, availability_zone):
58 """Add or modify a private DNS domain."""
59 body = {'domain_entry': {'scope': 'private',
60 'availability_zone': availability_zone}}
61 return self._update('/os-floating-ip-dns/%s' % _quote_domain(fqdomain),
62 body,
63 'domain_entry')
64
65 def create_public(self, fqdomain, project):
66 """Add or modify a public DNS domain."""
67 body = {'domain_entry': {'scope': 'public', 'project': project}}
68
69 return self._update('/os-floating-ip-dns/%s' % _quote_domain(fqdomain),
70 body, 'domain_entry')
71
72 def delete(self, fqdomain):
73 """Delete the specified domain."""
74 self._delete("/os-floating-ip-dns/%s" % _quote_domain(fqdomain))
75
76
77class FloatingIPDNSEntry(base.Resource):
78 def delete(self):
79 self.manager.delete(self.name, self.domain)
80
81 def create(self):
82 self.manager.create(self.domain, self.name, self.ip, self.dns_type)
83
84 def get(self):
85 return self.manager.get(self.domain, self.name)
86
87
88class FloatingIPDNSEntryManager(base.Manager):
89 resource_class = FloatingIPDNSEntry
90
91 def get(self, domain, name):
92 """Return a list of entries for the given domain and IP or name."""
93 return self._get("/os-floating-ip-dns/%s/entries/%s" %
94 (_quote_domain(domain), name), "dns_entry")
95
96 def get_for_ip(self, domain, ip):
97 """Return a list of entries for the given domain and IP or name."""
98 qparams = {'ip': ip}
99 params = "?%s" % parse.urlencode(qparams)
100
101 return self._list("/os-floating-ip-dns/%s/entries%s" %
102 (_quote_domain(domain), params), "dns_entries")
103
104 def create(self, domain, name, ip, dns_type):
105 """Add a new DNS entry."""
106 body = {'dns_entry': {'ip': ip, 'dns_type': dns_type}}
107
108 return self._update("/os-floating-ip-dns/%s/entries/%s" %
109 (_quote_domain(domain), name), body, "dns_entry")
110
111 def modify_ip(self, domain, name, ip):
112 """Add a new DNS entry."""
113 body = {'dns_entry': {'ip': ip, 'dns_type': 'A'}}
114
115 return self._update("/os-floating-ip-dns/%s/entries/%s" %
116 (_quote_domain(domain), name), body, "dns_entry")
117
118 def delete(self, domain, name):
119 """Delete entry specified by name and domain."""
120 self._delete("/os-floating-ip-dns/%s/entries/%s" %
121 (_quote_domain(domain), name))
diff --git a/novaclient/v2/floating_ip_pools.py b/novaclient/v2/floating_ip_pools.py
new file mode 100644
index 0000000..7666bd5
--- /dev/null
+++ b/novaclient/v2/floating_ip_pools.py
@@ -0,0 +1,32 @@
1# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
2#
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from novaclient import base
18
19
20class FloatingIPPool(base.Resource):
21 def __repr__(self):
22 return "<FloatingIPPool: name=%s>" % self.name
23
24
25class FloatingIPPoolManager(base.ManagerWithFind):
26 resource_class = FloatingIPPool
27
28 def list(self):
29 """
30 Retrieve a list of all floating ip pools.
31 """
32 return self._list('/os-floating-ip-pools', 'floating_ip_pools')
diff --git a/novaclient/v2/floating_ips.py b/novaclient/v2/floating_ips.py
new file mode 100644
index 0000000..cce92da
--- /dev/null
+++ b/novaclient/v2/floating_ips.py
@@ -0,0 +1,59 @@
1# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
2# Copyright 2011 OpenStack Foundation
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from novaclient import base
18
19
20class FloatingIP(base.Resource):
21 def delete(self):
22 """
23 Delete this floating IP
24 """
25 self.manager.delete(self)
26
27
28class FloatingIPManager(base.ManagerWithFind):
29 resource_class = FloatingIP
30
31 def list(self, all_tenants=False):
32 """
33 List floating IPs
34 """
35 url = '/os-floating-ips'
36 if all_tenants:
37 url += '?all_tenants=1'
38 return self._list(url, "floating_ips")
39
40 def create(self, pool=None):
41 """
42 Create (allocate) a floating IP for a tenant
43 """
44 return self._create("/os-floating-ips", {'pool': pool}, "floating_ip")
45
46 def delete(self, floating_ip):
47 """
48 Delete (deallocate) a floating IP for a tenant
49
50 :param floating_ip: The floating IP address to delete.
51 """
52 self._delete("/os-floating-ips/%s" % base.getid(floating_ip))
53
54 def get(self, floating_ip):
55 """
56 Retrieve a floating IP
57 """
58 return self._get("/os-floating-ips/%s" % base.getid(floating_ip),
59 "floating_ip")
diff --git a/novaclient/v2/floating_ips_bulk.py b/novaclient/v2/floating_ips_bulk.py
new file mode 100644
index 0000000..fb59a19
--- /dev/null
+++ b/novaclient/v2/floating_ips_bulk.py
@@ -0,0 +1,58 @@
1# Copyright 2012 IBM Corp.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Bulk Floating IPs interface
18"""
19from novaclient import base
20
21
22class FloatingIP(base.Resource):
23 def __repr__(self):
24 return "<FloatingIP: %s>" % self.address
25
26
27class FloatingIPBulkManager(base.ManagerWithFind):
28 resource_class = FloatingIP
29
30 def list(self, host=None):
31 """
32 List all floating IPs
33 """
34 if host is None:
35 return self._list('/os-floating-ips-bulk', 'floating_ip_info')
36 else:
37 return self._list('/os-floating-ips-bulk/%s' % host,
38 'floating_ip_info')
39
40 def create(self, ip_range, pool=None, interface=None):
41 """
42 Create floating IPs by range
43 """
44 body = {"floating_ips_bulk_create": {'ip_range': ip_range}}
45 if pool is not None:
46 body['floating_ips_bulk_create']['pool'] = pool
47 if interface is not None:
48 body['floating_ips_bulk_create']['interface'] = interface
49
50 return self._create('/os-floating-ips-bulk', body,
51 'floating_ips_bulk_create')
52
53 def delete(self, ip_range):
54 """
55 Delete floating IPs by range
56 """
57 body = {"ip_range": ip_range}
58 return self._update('/os-floating-ips-bulk/delete', body)
diff --git a/novaclient/v2/fping.py b/novaclient/v2/fping.py
new file mode 100644
index 0000000..ac958d4
--- /dev/null
+++ b/novaclient/v2/fping.py
@@ -0,0 +1,64 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Fping interface.
18"""
19
20from novaclient import base
21
22
23class Fping(base.Resource):
24 """
25 A server to fping.
26 """
27 HUMAN_ID = True
28
29 def __repr__(self):
30 return "<Fping: %s>" % self.id
31
32
33class FpingManager(base.ManagerWithFind):
34 """
35 Manage :class:`Fping` resources.
36 """
37 resource_class = Fping
38
39 def list(self, all_tenants=False, include=[], exclude=[]):
40 """
41 Fping all servers.
42
43 :rtype: list of :class:`Fping`.
44 """
45 params = []
46 if all_tenants:
47 params.append("all_tenants=1")
48 if include:
49 params.append("include=%s" % ",".join(include))
50 elif exclude:
51 params.append("exclude=%s" % ",".join(exclude))
52 uri = "/os-fping"
53 if params:
54 uri = "%s?%s" % (uri, "&".join(params))
55 return self._list(uri, "servers")
56
57 def get(self, server):
58 """
59 Fping a specific server.
60
61 :param network: ID of the server to fping.
62 :rtype: :class:`Fping`
63 """
64 return self._get("/os-fping/%s" % base.getid(server), "server")
diff --git a/novaclient/v2/hosts.py b/novaclient/v2/hosts.py
new file mode 100644
index 0000000..af1756a
--- /dev/null
+++ b/novaclient/v2/hosts.py
@@ -0,0 +1,70 @@
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17host interface (1.1 extension).
18"""
19from novaclient import base
20
21
22class Host(base.Resource):
23 def __repr__(self):
24 return "<Host: %s>" % self.host
25
26 def _add_details(self, info):
27 dico = 'resource' in info and info['resource'] or info
28 for (k, v) in dico.items():
29 setattr(self, k, v)
30
31 def update(self, values):
32 return self.manager.update(self.host, values)
33
34 def startup(self):
35 return self.manager.host_action(self.host, 'startup')
36
37 def shutdown(self):
38 return self.manager.host_action(self.host, 'shutdown')
39
40 def reboot(self):
41 return self.manager.host_action(self.host, 'reboot')
42
43
44class HostManager(base.ManagerWithFind):
45 resource_class = Host
46
47 def get(self, host):
48 """
49 Describes cpu/memory/hdd info for host.
50
51 :param host: destination host name.
52 """
53 return self._list("/os-hosts/%s" % host, "host")
54
55 def update(self, host, values):
56 """Update status or maintenance mode for the host."""
57 return self._update("/os-hosts/%s" % host, values)
58
59 def host_action(self, host, action):
60 """Perform an action on a host."""
61 url = '/os-hosts/{0}/{1}'.format(host, action)
62 return self.api.client.get(url)
63
64 def list(self, zone=None):
65 url = '/os-hosts'
66 if zone:
67 url = '/os-hosts?zone=%s' % zone
68 return self._list(url, "hosts")
69
70 list_all = list
diff --git a/novaclient/v2/hypervisors.py b/novaclient/v2/hypervisors.py
new file mode 100644
index 0000000..b1bfcb4
--- /dev/null
+++ b/novaclient/v2/hypervisors.py
@@ -0,0 +1,92 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Hypervisors interface (1.1 extension).
18"""
19
20from six.moves.urllib import parse
21
22from novaclient import base
23
24
25class Hypervisor(base.Resource):
26 NAME_ATTR = 'hypervisor_hostname'
27
28 def __repr__(self):
29 return "<Hypervisor: %s>" % self.id
30
31
32class HypervisorManager(base.ManagerWithFind):
33 resource_class = Hypervisor
34
35 def list(self, detailed=True):
36 """
37 Get a list of hypervisors.
38 """
39 detail = ""
40 if detailed:
41 detail = "/detail"
42 return self._list('/os-hypervisors%s' % detail, 'hypervisors')
43
44 def search(self, hypervisor_match, servers=False):
45 """
46 Get a list of matching hypervisors.
47
48 :param servers: If True, server information is also retrieved.
49 """
50 target = 'servers' if servers else 'search'
51 url = ('/os-hypervisors/%s/%s' %
52 (parse.quote(hypervisor_match, safe=''), target))
53 return self._list(url, 'hypervisors')
54
55 def get(self, hypervisor):
56 """
57 Get a specific hypervisor.
58 """
59 return self._get("/os-hypervisors/%s" % base.getid(hypervisor),
60 "hypervisor")
61
62 def uptime(self, hypervisor):
63 """
64 Get the uptime for a specific hypervisor.
65 """
66 return self._get("/os-hypervisors/%s/uptime" % base.getid(hypervisor),
67 "hypervisor")
68
69 def statistics(self):
70 """
71 Get hypervisor statistics over all compute nodes.
72
73 Kept for backwards compatibility, new code should call
74 hypervisor_stats.statistics() instead of hypervisors.statistics()
75 """
76 return self.api.hypervisor_stats.statistics()
77
78
79class HypervisorStats(base.Resource):
80 def __repr__(self):
81 return ("<HypervisorStats: %d Hypervisor%s>" %
82 (self.count, "s" if self.count != 1 else ""))
83
84
85class HypervisorStatsManager(base.Manager):
86 resource_class = HypervisorStats
87
88 def statistics(self):
89 """
90 Get hypervisor statistics over all compute nodes.
91 """
92 return self._get("/os-hypervisors/statistics", "hypervisor_statistics")
diff --git a/novaclient/v2/images.py b/novaclient/v2/images.py
new file mode 100644
index 0000000..2d413a6
--- /dev/null
+++ b/novaclient/v2/images.py
@@ -0,0 +1,101 @@
1# Copyright 2010 Jacob Kaplan-Moss
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16Image interface.
17"""
18
19from six.moves.urllib import parse
20
21from novaclient import base
22
23
24class Image(base.Resource):
25 """
26 An image is a collection of files used to create or rebuild a server.
27 """
28 HUMAN_ID = True
29
30 def __repr__(self):
31 return "<Image: %s>" % self.name
32
33 def delete(self):
34 """
35 Delete this image.
36 """
37 self.manager.delete(self)
38
39
40class ImageManager(base.ManagerWithFind):
41 """
42 Manage :class:`Image` resources.
43 """
44 resource_class = Image
45
46 def get(self, image):
47 """
48 Get an image.
49
50 :param image: The ID of the image to get.
51 :rtype: :class:`Image`
52 """
53 return self._get("/images/%s" % base.getid(image), "image")
54
55 def list(self, detailed=True, limit=None):
56 """
57 Get a list of all images.
58
59 :rtype: list of :class:`Image`
60 :param limit: maximum number of images to return.
61 """
62 params = {}
63 detail = ''
64 if detailed:
65 detail = '/detail'
66 if limit:
67 params['limit'] = int(limit)
68 query = '?%s' % parse.urlencode(params) if params else ''
69 return self._list('/images%s%s' % (detail, query), 'images')
70
71 def delete(self, image):
72 """
73 Delete an image.
74
75 It should go without saying that you can't delete an image
76 that you didn't create.
77
78 :param image: The :class:`Image` (or its ID) to delete.
79 """
80 self._delete("/images/%s" % base.getid(image))
81
82 def set_meta(self, image, metadata):
83 """
84 Set an images metadata
85
86 :param image: The :class:`Image` to add metadata to
87 :param metadata: A dict of metadata to add to the image
88 """
89 body = {'metadata': metadata}
90 return self._create("/images/%s/metadata" % base.getid(image),
91 body, "metadata")
92
93 def delete_meta(self, image, keys):
94 """
95 Delete metadata from an image
96
97 :param image: The :class:`Image` to delete metadata
98 :param keys: A list of metadata keys to delete from the image
99 """
100 for k in keys:
101 self._delete("/images/%s/metadata/%s" % (base.getid(image), k))
diff --git a/novaclient/v2/keypairs.py b/novaclient/v2/keypairs.py
new file mode 100644
index 0000000..96caff6
--- /dev/null
+++ b/novaclient/v2/keypairs.py
@@ -0,0 +1,92 @@
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Keypair interface (1.1 extension).
18"""
19
20from novaclient import base
21
22
23class Keypair(base.Resource):
24 """
25 A keypair is a ssh key that can be injected into a server on launch.
26 """
27
28 def __repr__(self):
29 return "<Keypair: %s>" % self.id
30
31 def _add_details(self, info):
32 dico = 'keypair' in info and \
33 info['keypair'] or info
34 for (k, v) in dico.items():
35 # NOTE(rpodolyaka): keypair name allows us to uniquely identify
36 # a specific keypair, while its id attribute
37 # is nothing more than an implementation
38 # detail. We can safely omit the id attribute
39 # here to ensure setattr() won't raise
40 # AttributeError trying to set read-only
41 # property id
42 if k != 'id':
43 setattr(self, k, v)
44
45 @property
46 def id(self):
47 return self.name
48
49 def delete(self):
50 self.manager.delete(self)
51
52
53class KeypairManager(base.ManagerWithFind):
54 resource_class = Keypair
55 keypair_prefix = "os-keypairs"
56 is_alphanum_id_allowed = True
57
58 def get(self, keypair):
59 """
60 Get a keypair.
61
62 :param keypair: The ID of the keypair to get.
63 :rtype: :class:`Keypair`
64 """
65 return self._get("/%s/%s" % (self.keypair_prefix, base.getid(keypair)),
66 "keypair")
67
68 def create(self, name, public_key=None):
69 """
70 Create a keypair
71
72 :param name: name for the keypair to create
73 :param public_key: existing public key to import
74 """
75 body = {'keypair': {'name': name}}
76 if public_key:
77 body['keypair']['public_key'] = public_key
78 return self._create('/%s' % self.keypair_prefix, body, 'keypair')
79
80 def delete(self, key):
81 """
82 Delete a keypair
83
84 :param key: The :class:`Keypair` (or its ID) to delete.
85 """
86 self._delete('/%s/%s' % (self.keypair_prefix, base.getid(key)))
87
88 def list(self):
89 """
90 Get a list of keypairs.
91 """
92 return self._list('/%s' % self.keypair_prefix, 'keypairs')
diff --git a/novaclient/v2/limits.py b/novaclient/v2/limits.py
new file mode 100644
index 0000000..46d77de
--- /dev/null
+++ b/novaclient/v2/limits.py
@@ -0,0 +1,100 @@
1# Copyright 2011 OpenStack Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from six.moves.urllib import parse
16
17from novaclient import base
18
19
20class Limits(base.Resource):
21 """A collection of RateLimit and AbsoluteLimit objects."""
22
23 def __repr__(self):
24 return "<Limits>"
25
26 @property
27 def absolute(self):
28 for (name, value) in self._info['absolute'].items():
29 yield AbsoluteLimit(name, value)
30
31 @property
32 def rate(self):
33 for group in self._info['rate']:
34 uri = group['uri']
35 regex = group['regex']
36 for rate in group['limit']:
37 yield RateLimit(rate['verb'], uri, regex, rate['value'],
38 rate['remaining'], rate['unit'],
39 rate['next-available'])
40
41
42class RateLimit(object):
43 """Data model that represents a flattened view of a single rate limit."""
44
45 def __init__(self, verb, uri, regex, value, remain,
46 unit, next_available):
47 self.verb = verb
48 self.uri = uri
49 self.regex = regex
50 self.value = value
51 self.remain = remain
52 self.unit = unit
53 self.next_available = next_available
54
55 def __eq__(self, other):
56 return self.uri == other.uri \
57 and self.regex == other.regex \
58 and self.value == other.value \
59 and self.verb == other.verb \
60 and self.remain == other.remain \
61 and self.unit == other.unit \
62 and self.next_available == other.next_available
63
64 def __repr__(self):
65 return "<RateLimit: verb=%s uri=%s>" % (self.verb, self.uri)
66
67
68class AbsoluteLimit(object):
69 """Data model that represents a single absolute limit."""
70
71 def __init__(self, name, value):
72 self.name = name
73 self.value = value
74
75 def __eq__(self, other):
76 return self.value == other.value and self.name == other.name
77
78 def __repr__(self):
79 return "<AbsoluteLimit: name=%s>" % (self.name)
80
81
82class LimitsManager(base.Manager):
83 """Manager object used to interact with limits resource."""
84
85 resource_class = Limits
86
87 def get(self, reserved=False, tenant_id=None):
88 """
89 Get a specific extension.
90
91 :rtype: :class:`Limits`
92 """
93 opts = {}
94 if reserved:
95 opts['reserved'] = 1
96 if tenant_id:
97 opts['tenant_id'] = tenant_id
98 query_string = "?%s" % parse.urlencode(opts) if opts else ""
99
100 return self._get("/limits%s" % query_string, "limits")
diff --git a/novaclient/v2/networks.py b/novaclient/v2/networks.py
new file mode 100644
index 0000000..06dee27
--- /dev/null
+++ b/novaclient/v2/networks.py
@@ -0,0 +1,156 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Network interface.
18"""
19
20from novaclient import base
21from novaclient import exceptions
22from novaclient.i18n import _
23
24
25class Network(base.Resource):
26 """
27 A network.
28 """
29 HUMAN_ID = True
30 NAME_ATTR = "label"
31
32 def __repr__(self):
33 return "<Network: %s>" % self.label
34
35 def delete(self):
36 self.manager.delete(self)
37
38
39class NetworkManager(base.ManagerWithFind):
40 """
41 Manage :class:`Network` resources.
42 """
43 resource_class = Network
44
45 def list(self):
46 """
47 Get a list of all networks.
48
49 :rtype: list of :class:`Network`.
50 """
51 return self._list("/os-networks", "networks")
52
53 def get(self, network):
54 """
55 Get a specific network.
56
57 :param network: The ID of the :class:`Network` to get.
58 :rtype: :class:`Network`
59 """
60 return self._get("/os-networks/%s" % base.getid(network),
61 "network")
62
63 def delete(self, network):
64 """
65 Delete a specific network.
66
67 :param network: The ID of the :class:`Network` to delete.
68 """
69 self._delete("/os-networks/%s" % base.getid(network))
70
71 def create(self, **kwargs):
72 """
73 Create (allocate) a network. The following parameters are
74 optional except for label; cidr or cidr_v6 must be specified, too.
75
76 :param label: str
77 :param bridge: str
78 :param bridge_interface: str
79 :param cidr: str
80 :param cidr_v6: str
81 :param dns1: str
82 :param dns2: str
83 :param fixed_cidr: str
84 :param gateway: str
85 :param gateway_v6: str
86 :param multi_host: str
87 :param priority: str
88 :param project_id: str
89 :param vlan: int
90 :param vlan_start: int
91 :param vpn_start: int
92 :param mtu: int
93 :param enable_dhcp: int
94 :param dhcp_server: str
95 :param share_address: int
96 :param allowed_start: str
97 :param allowed_end: str
98
99 :rtype: object of :class:`Network`
100 """
101 body = {"network": kwargs}
102 return self._create('/os-networks', body, 'network')
103
104 def disassociate(self, network, disassociate_host=True,
105 disassociate_project=True):
106 """
107 Disassociate a specific network from project and/or host.
108
109 :param network: The ID of the :class:`Network`.
110 :param disassociate_host: Whether to disassociate the host
111 :param disassociate_project: Whether to disassociate the project
112 """
113 if disassociate_host and disassociate_project:
114 body = {"disassociate": None}
115 elif disassociate_project:
116 body = {"disassociate_project": None}
117 elif disassociate_host:
118 body = {"disassociate_host": None}
119 else:
120 raise exceptions.CommandError(
121 _("Must disassociate either host or project or both"))
122
123 self.api.client.post("/os-networks/%s/action" %
124 base.getid(network), body=body)
125
126 def associate_host(self, network, host):
127 """
128 Associate a specific network with a host.
129
130 :param network: The ID of the :class:`Network`.
131 :param host: The name of the host to associate the network with
132 """
133 self.api.client.post("/os-networks/%s/action" %
134 base.getid(network),
135 body={"associate_host": host})
136
137 def associate_project(self, network):
138 """
139 Associate a specific network with a project.
140
141 The project is defined by the project authenticated against
142
143 :param network: The ID of the :class:`Network`.
144 """
145 self.api.client.post("/os-networks/add", body={"id": network})
146
147 def add(self, network=None):
148 """
149 Associates the current project with a network. Network can be chosen
150 automatically or provided explicitly.
151
152 :param network: The ID of the :class:`Network` to associate (optional).
153 """
154 self.api.client.post(
155 "/os-networks/add",
156 body={"id": base.getid(network) if network else None})
diff --git a/novaclient/v2/quota_classes.py b/novaclient/v2/quota_classes.py
new file mode 100644
index 0000000..4a38a97
--- /dev/null
+++ b/novaclient/v2/quota_classes.py
@@ -0,0 +1,44 @@
1# Copyright 2012 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import base
17
18
19class QuotaClassSet(base.Resource):
20
21 def update(self, *args, **kwargs):
22 return self.manager.update(self.id, *args, **kwargs)
23
24
25class QuotaClassSetManager(base.Manager):
26 resource_class = QuotaClassSet
27
28 def get(self, class_name):
29 return self._get("/os-quota-class-sets/%s" % (class_name),
30 "quota_class_set")
31
32 def _update_body(self, **kwargs):
33 return {'quota_class_set': kwargs}
34
35 def update(self, class_name, **kwargs):
36 body = self._update_body(**kwargs)
37
38 for key in list(body['quota_class_set']):
39 if body['quota_class_set'][key] is None:
40 body['quota_class_set'].pop(key)
41
42 return self._update('/os-quota-class-sets/%s' % (class_name),
43 body,
44 'quota_class_set')
diff --git a/novaclient/v2/quotas.py b/novaclient/v2/quotas.py
new file mode 100644
index 0000000..cd16042
--- /dev/null
+++ b/novaclient/v2/quotas.py
@@ -0,0 +1,72 @@
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from novaclient import base
17
18
19class QuotaSet(base.Resource):
20
21 @property
22 def id(self):
23 """QuotaSet does not have a 'id' attribute but base.Resource needs it
24 to self-refresh and QuotaSet is indexed by tenant_id.
25 """
26 return self.tenant_id
27
28 def update(self, *args, **kwargs):
29 return self.manager.update(self.tenant_id, *args, **kwargs)
30
31
32class QuotaSetManager(base.Manager):
33 resource_class = QuotaSet
34
35 def get(self, tenant_id, user_id=None):
36 if hasattr(tenant_id, 'tenant_id'):
37 tenant_id = tenant_id.tenant_id
38 if user_id:
39 url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id)
40 else:
41 url = '/os-quota-sets/%s' % tenant_id
42 return self._get(url, "quota_set")
43
44 def _update_body(self, tenant_id, **kwargs):
45 kwargs['tenant_id'] = tenant_id
46 return {'quota_set': kwargs}
47
48 def update(self, tenant_id, **kwargs):
49
50 user_id = kwargs.pop('user_id', None)
51 body = self._update_body(tenant_id, **kwargs)
52
53 for key in list(body['quota_set']):
54 if body['quota_set'][key] is None:
55 body['quota_set'].pop(key)
56
57 if user_id:
58 url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id)
59 else:
60 url = '/os-quota-sets/%s' % tenant_id
61 return self._update(url, body, 'quota_set')
62
63 def defaults(self, tenant_id):
64 return self._get('/os-quota-sets/%s/defaults' % tenant_id,
65 'quota_set')
66
67 def delete(self, tenant_id, user_id=None):
68 if user_id:
69 url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id)
70 else:
71 url = '/os-quota-sets/%s' % tenant_id
72 self._delete(url)
diff --git a/novaclient/v2/security_group_default_rules.py b/novaclient/v2/security_group_default_rules.py
new file mode 100644
index 0000000..d82a1d8
--- /dev/null
+++ b/novaclient/v2/security_group_default_rules.py
@@ -0,0 +1,81 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13"""
14Security group default rules interface.
15"""
16
17from novaclient import base
18from novaclient import exceptions
19from novaclient.i18n import _
20
21
22class SecurityGroupDefaultRule(base.Resource):
23 def __str__(self):
24 return str(self.id)
25
26 def delete(self):
27 self.manager.delete(self)
28
29
30class SecurityGroupDefaultRuleManager(base.Manager):
31 resource_class = SecurityGroupDefaultRule
32
33 def create(self, ip_protocol=None, from_port=None, to_port=None,
34 cidr=None):
35 """
36 Create a security group default rule
37
38 :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp'
39 :param from_port: Source port
40 :param to_port: Destination port
41 :param cidr: Destination IP address(es) in CIDR notation
42 """
43
44 try:
45 from_port = int(from_port)
46 except (TypeError, ValueError):
47 raise exceptions.CommandError(_("From port must be an integer."))
48 try:
49 to_port = int(to_port)
50 except (TypeError, ValueError):
51 raise exceptions.CommandError(_("To port must be an integer."))
52 if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']:
53 raise exceptions.CommandError(_("IP protocol must be 'tcp', 'udp'"
54 ", or 'icmp'."))
55
56 body = {"security_group_default_rule": {
57 "ip_protocol": ip_protocol,
58 "from_port": from_port,
59 "to_port": to_port,
60 "cidr": cidr}}
61
62 return self._create('/os-security-group-default-rules', body,
63 'security_group_default_rule')
64
65 def delete(self, rule):
66 """
67 Delete a security group default rule
68
69 :param rule: The security group default rule to delete (ID or Class)
70 """
71 self._delete('/os-security-group-default-rules/%s' % base.getid(rule))
72
73 def list(self):
74 """
75 Get a list of all security group default rules
76
77 :rtype: list of :class:`SecurityGroupDefaultRule`
78 """
79
80 return self._list('/os-security-group-default-rules',
81 'security_group_default_rules')
diff --git a/novaclient/v2/security_group_rules.py b/novaclient/v2/security_group_rules.py
new file mode 100644
index 0000000..4cb51b0
--- /dev/null
+++ b/novaclient/v2/security_group_rules.py
@@ -0,0 +1,78 @@
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Security group rules interface (1.1 extension).
18"""
19
20from novaclient import base
21from novaclient import exceptions
22from novaclient.i18n import _
23
24
25class SecurityGroupRule(base.Resource):
26 def __str__(self):
27 return str(self.id)
28
29 def delete(self):
30 self.manager.delete(self)
31
32
33class SecurityGroupRuleManager(base.Manager):
34 resource_class = SecurityGroupRule
35
36 def create(self, parent_group_id, ip_protocol=None, from_port=None,
37 to_port=None, cidr=None, group_id=None):
38 """
39 Create a security group rule
40
41 :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp'
42 :param from_port: Source port
43 :param to_port: Destination port
44 :param cidr: Destination IP address(es) in CIDR notation
45 :param group_id: Security group id (int)
46 :param parent_group_id: Parent security group id (int)
47 """
48
49 try:
50 from_port = int(from_port)
51 except (TypeError, ValueError):
52 raise exceptions.CommandError(_("From port must be an integer."))
53 try:
54 to_port = int(to_port)
55 except (TypeError, ValueError):
56 raise exceptions.CommandError(_("To port must be an integer."))
57 if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']:
58 raise exceptions.CommandError(_("IP protocol must be 'tcp', 'udp'"
59 ", or 'icmp'."))
60
61 body = {"security_group_rule": {
62 "ip_protocol": ip_protocol,
63 "from_port": from_port,
64 "to_port": to_port,
65 "cidr": cidr,
66 "group_id": group_id,
67 "parent_group_id": parent_group_id}}
68
69 return self._create('/os-security-group-rules', body,
70 'security_group_rule')
71
72 def delete(self, rule):
73 """
74 Delete a security group rule
75
76 :param rule: The security group rule to delete (ID or Class)
77 """
78 self._delete('/os-security-group-rules/%s' % base.getid(rule))
diff --git a/novaclient/v2/security_groups.py b/novaclient/v2/security_groups.py
new file mode 100644
index 0000000..40d1e7f
--- /dev/null
+++ b/novaclient/v2/security_groups.py
@@ -0,0 +1,96 @@
1# Copyright 2011 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Security group interface (1.1 extension).
18"""
19
20import six
21from six.moves.urllib import parse
22
23from novaclient import base
24
25
26class SecurityGroup(base.Resource):
27 def __str__(self):
28 return str(self.id)
29
30 def delete(self):
31 self.manager.delete(self)
32
33 def update(self):
34 self.manager.update(self)
35
36
37class SecurityGroupManager(base.ManagerWithFind):
38 resource_class = SecurityGroup
39
40 def create(self, name, description):
41 """
42 Create a security group
43
44 :param name: name for the security group to create
45 :param description: description of the security group
46 :rtype: the security group object
47 """
48 body = {"security_group": {"name": name, 'description': description}}
49 return self._create('/os-security-groups', body, 'security_group')
50
51 def update(self, group, name, description):
52 """
53 Update a security group
54
55 :param group: The security group to update (group or ID)
56 :param name: name for the security group to update
57 :param description: description for the security group to update
58 :rtype: the security group object
59 """
60 body = {"security_group": {"name": name, 'description': description}}
61 return self._update('/os-security-groups/%s' % base.getid(group),
62 body, 'security_group')
63
64 def delete(self, group):
65 """
66 Delete a security group
67
68 :param group: The security group to delete (group or ID)
69 :rtype: None
70 """
71 self._delete('/os-security-groups/%s' % base.getid(group))
72
73 def get(self, group_id):
74 """
75 Get a security group
76
77 :param group_id: The security group to get by ID
78 :rtype: :class:`SecurityGroup`
79 """
80 return self._get('/os-security-groups/%s' % group_id,
81 'security_group')
82
83 def list(self, search_opts=None):
84 """
85 Get a list of all security_groups
86
87 :rtype: list of :class:`SecurityGroup`
88 """
89 search_opts = search_opts or {}
90
91 qparams = dict((k, v) for (k, v) in six.iteritems(search_opts) if v)
92
93 query_string = '?%s' % parse.urlencode(qparams) if qparams else ''
94
95 return self._list('/os-security-groups%s' % query_string,
96 'security_groups')
diff --git a/novaclient/v2/server_groups.py b/novaclient/v2/server_groups.py
new file mode 100644
index 0000000..a5205e7
--- /dev/null
+++ b/novaclient/v2/server_groups.py
@@ -0,0 +1,71 @@
1# Copyright (c) 2014 VMware, Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""
17Server group interface.
18"""
19
20from novaclient import base
21
22
23class ServerGroup(base.Resource):
24 """
25 A server group.
26 """
27 NAME_ATTR = 'server_group_name'
28
29 def __repr__(self):
30 return '<ServerGroup: %s>' % self.id
31
32 def delete(self):
33 self.manager.delete(self.id)
34
35
36class ServerGroupsManager(base.ManagerWithFind):
37 """
38 Manage :class:`ServerGroup` resources.
39 """
40 resource_class = ServerGroup
41
42 def list(self):
43 """Get a list of all server groups.
44
45 :rtype: list of :class:`ServerGroup`.
46 """
47 return self._list('/os-server-groups', 'server_groups')
48
49 def get(self, id):
50 """Get a specific server group.
51
52 :param id: The ID of the :class:`ServerGroup` to get.
53 :rtype: :class:`ServerGroup`
54 """
55 return self._get('/os-server-groups/%s' % id,
56 'server_group')
57
58 def delete(self, id):
59 """Delete a specific server group.
60
61 :param id: The ID of the :class:`ServerGroup` to delete.
62 """
63 self._delete('/os-server-groups/%s' % id)
64
65 def create(self, **kwargs):
66 """Create (allocate) a server group.
67
68 :rtype: list of :class:`ServerGroup`
69 """
70 body = {'server_group': kwargs}
71 return self._create('/os-server-groups', body, 'server_group')
diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py
new file mode 100644
index 0000000..36de45b
--- /dev/null
+++ b/novaclient/v2/servers.py
@@ -0,0 +1,1274 @@
1# Copyright 2010 Jacob Kaplan-Moss
2
3# Copyright 2011 OpenStack Foundation
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18"""
19Server interface.
20"""
21
22import base64
23
24from oslo.utils import encodeutils
25import six
26from six.moves.urllib import parse
27
28from novaclient import base
29from novaclient import crypto
30from novaclient.i18n import _
31from novaclient.v2 import security_groups
32
33
34REBOOT_SOFT, REBOOT_HARD = 'SOFT', 'HARD'
35
36
37class Server(base.Resource):
38 HUMAN_ID = True
39
40 def __repr__(self):
41 return '<Server: %s>' % getattr(self, 'name', 'unknown-name')
42
43 def delete(self):
44 """
45 Delete (i.e. shut down and delete the image) this server.
46 """
47 self.manager.delete(self)
48
49 def update(self, name=None):
50 """
51 Update the name for this server.
52
53 :param name: Update the server's name.
54 """
55 self.manager.update(self, name=name)
56
57 def get_console_output(self, length=None):
58 """
59 Get text console log output from Server.
60
61 :param length: The number of lines you would like to retrieve (as int)
62 """
63 return self.manager.get_console_output(self, length)
64
65 def get_vnc_console(self, console_type):
66 """
67 Get vnc console for a Server.
68
69 :param console_type: Type of console ('novnc' or 'xvpvnc')
70 """
71 return self.manager.get_vnc_console(self, console_type)
72
73 def get_spice_console(self, console_type):
74 """
75 Get spice console for a Server.
76
77 :param console_type: Type of console ('spice-html5')
78 """
79 return self.manager.get_spice_console(self, console_type)
80
81 def get_rdp_console(self, console_type):
82 """
83 Get rdp console for a Server.
84
85 :param console_type: Type of console ('rdp-html5')
86 """
87 return self.manager.get_rdp_console(self, console_type)
88
89 def get_serial_console(self, console_type):
90 """
91 Get serial console for a Server.
92
93 :param console_type: Type of console ('serial')
94 """
95 return self.manager.get_serial_console(self, console_type)
96
97 def get_password(self, private_key=None):
98 """
99 Get password for a Server.
100
101 Returns the clear password of an instance if private_key is
102 provided, returns the ciphered password otherwise.
103
104 :param private_key: Path to private key file for decryption
105 (optional)
106 """
107 return self.manager.get_password(self, private_key)
108
109 def clear_password(self):
110 """
111 Get password for a Server.
112
113 """
114 return self.manager.clear_password(self)
115
116 def add_fixed_ip(self, network_id):
117 """
118 Add an IP address on a network.
119
120 :param network_id: The ID of the network the IP should be on.
121 """
122 self.manager.add_fixed_ip(self, network_id)
123
124 def add_floating_ip(self, address, fixed_address=None):
125 """
126 Add floating IP to an instance
127
128 :param address: The IP address or FloatingIP to add to the instance
129 :param fixed_address: The fixedIP address the FloatingIP is to be
130 associated with (optional)
131 """
132 self.manager.add_floating_ip(self, address, fixed_address)
133
134 def remove_floating_ip(self, address):
135 """
136 Remove floating IP from an instance
137
138 :param address: The IP address or FloatingIP to remove
139 """
140 self.manager.remove_floating_ip(self, address)
141
142 def stop(self):
143 """
144 Stop -- Stop the running server.
145 """
146 self.manager.stop(self)
147
148 def force_delete(self):
149 """
150 Force delete -- Force delete a server.
151 """
152 self.manager.force_delete(self)
153
154 def restore(self):
155 """
156 Restore -- Restore a server in 'soft-deleted' state.
157 """
158 self.manager.restore(self)
159
160 def start(self):
161 """
162 Start -- Start the paused server.
163 """
164 self.manager.start(self)
165
166 def pause(self):
167 """
168 Pause -- Pause the running server.
169 """
170 self.manager.pause(self)
171
172 def unpause(self):
173 """
174 Unpause -- Unpause the paused server.
175 """
176 self.manager.unpause(self)
177
178 def lock(self):
179 """
180 Lock -- Lock the instance from certain operations.
181 """
182 self.manager.lock(self)
183
184 def unlock(self):
185 """
186 Unlock -- Remove instance lock.
187 """
188 self.manager.unlock(self)
189
190 def suspend(self):
191 """
192 Suspend -- Suspend the running server.
193 """
194 self.manager.suspend(self)
195
196 def resume(self):
197 """
198 Resume -- Resume the suspended server.
199 """
200 self.manager.resume(self)