找回密码
 注册
查看: 2197|回复: 2

openstack使用ansible nova配置

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2021-9-3 15:45:36 | 显示全部楼层 |阅读模式
/usr/lib/python2.7/site-packages/openstack/compute/v2) O! b+ A) Q& G7 P0 Z  @
server.py$ u' N1 w- v9 W+ I
文件内容:" N7 W+ D0 d0 z4 X* Z+ X8 m; i) S
: [6 H- \: F0 @2 B; Q" t& m8 ^  ]
# Licensed under the Apache License, Version 2.0 (the "License"); you may1 T; ^- O& G7 B/ Q  }
# not use this file except in compliance with the License. You may obtain# v, P* ~; C* g6 V, N. a
# a copy of the License at9 o' p* _! c7 d: u
#
8 o) T4 [7 q9 p8 L- Y+ b#      http://www.apache.org/licenses/LICENSE-2.0
  d4 }" W% P9 I1 b  s; h" S+ T$ _#! j# w0 a/ R6 }. U
# Unless required by applicable law or agreed to in writing, software
& D: Z3 W8 z3 y' V# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
: W6 n$ P6 C) a) c5 E* G5 X( x# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
8 [( `: y3 s" I* {+ y# License for the specific language governing permissions and limitations
# g: U- @- @4 M7 R- _7 x& ^; y" k9 E# under the License.
3 \* @8 V3 c/ T: Lfrom openstack.compute.v2 import metadata
5 h1 X1 }% o/ i+ G3 rfrom openstack.image.v2 import image% }% x) P6 H0 t+ H, C7 F
from openstack import exceptions2 ]. ~9 }" {6 z" `& [& P) X
from openstack import resource' c: J& b& E7 h! w
from openstack import utils
8 Q8 |  M( m: C3 ^, w* ?3 c6 s% p# NCONSOLE_TYPE_ACTION_MAPPING = {1 `. n. O. N- L: Z" z. O
    'novnc': 'os-getVNCConsole'," j$ F. J; R2 y/ g
    'xvpvnc': 'os-getVNCConsole',
. a* k8 {2 \$ e) u+ b    'spice-html5': 'os-getSPICEConsole',' u- A, f( s# i- b- i+ r
    'rdp-html5': 'os-getRDPConsole',
- I& {7 L; }7 K8 [( r    'serial': 'os-getSerialConsole'
8 h) V% Y2 S! E3 u}3 H0 `, r0 [" w* a1 A$ {
class Server(resource.Resource, metadata.MetadataMixin, resource.TagMixin):/ X; D* P1 u$ q
    resource_key = 'server'& q% R; j! K* v. g
    resources_key = 'servers'
9 b, ]' a- n! A2 ]- f' F5 j1 r    base_path = '/servers'
5 f+ z1 a" S6 B: L5 [$ L    # capabilities
- n! G5 y6 u% @0 u$ M4 D# x5 w    allow_create = True3 t0 S3 C4 j" F* o/ R* p) d
    allow_fetch = True
0 ]+ q3 h( X' G" U! h. n4 |5 L    allow_commit = True
9 @2 o- A, C" R8 J    allow_delete = True
/ J4 Y" M" a( J6 A% M$ ]( T/ F    allow_list = True' f! s, b: Q' g8 Y9 S
    _query_mapping = resource.QueryParameters(
( Q( R8 t3 l; t0 g) Z) |$ i        "auto_disk_config", "availability_zone",9 f( C2 H7 G5 N+ x2 T! E
        "created_at", "description", "flavor",' ^; u4 D2 R3 }. ?7 ]5 X* H( F2 E4 ~
        "hostname", "image", "kernel_id", "key_name",
, f8 c; i! p: \  u% W        "launch_index", "launched_at", "locked_by", "name",
3 W; {+ d% p8 P' {# b8 ?7 c        "node", "power_state", "progress", "project_id", "ramdisk_id",! e: n- T: E: A
        "reservation_id", "root_device_name",
2 T1 ~7 j, B8 y: b3 l1 ]        "status", "task_state", "terminated_at", "user_id",8 Q! u9 }' W" d2 I$ t- S! Y
        "vm_state",) _1 q2 }7 ^5 O% B. R/ n
        "sort_key", "sort_dir",
3 ~( I. D* U# \- i        access_ipv4="access_ip_v4",
( X  P2 ^- x/ L/ g) E        access_ipv6="access_ip_v6",/ |0 w  U* y4 Z
        has_config_drive="config_drive",
1 g, J5 t  r1 ]9 x        deleted_only="deleted",2 W: c$ a1 D' l1 a. y- m
        compute_host="host",. E, E4 w. n2 L8 q$ }
        is_soft_deleted="soft_deleted",* u) O6 K; I# E, q/ @6 ?0 I
        ipv4_address="ip",
7 e4 Y7 n5 \/ e2 H3 f, C        ipv6_address="ip6",; Q1 N' Z2 Y- p* ~0 g7 C, q
        changes_since="changes-since",4 e+ a4 Y: o0 }! c$ d$ _0 e0 v
        changes_before="changes-before",/ t1 M, j5 g3 p2 ^& u# y: y
        id="uuid",( |6 E% ^& y" L
        all_projects="all_tenants",+ u- n, v" c) g
        **resource.TagMixin._tag_query_parameters
% n. {5 u% b" X    )& U6 g9 r3 I4 l; p3 @+ i' B' {
    _max_microversion = '2.72'
2 ?3 X/ d2 C; a$ Z    #: A list of dictionaries holding links relevant to this server.* t* M. z0 A( }1 |' o
    links = resource.Body('links')) ~) I6 @9 |) J8 r& L  [5 ^# s
    access_ipv4 = resource.Body('accessIPv4')' S% [. a, A- m  h
    access_ipv6 = resource.Body('accessIPv6')3 q9 |( _& r. M' d) m
    #: A dictionary of addresses this server can be accessed through.
2 ?5 E8 q% ?8 o4 W    #: The dictionary contains keys such as ``private`` and ``public``,
- H& d) `3 b* W    #: each containing a list of dictionaries for addresses of that type.
! c) u( S" E& K( Y- Z& }    #: The addresses are contained in a dictionary with keys ``addr``
  w' u- }) n; A. q$ i/ u9 t    #: and ``version``, which is either 4 or 6 depending on the protocol
7 O5 ]8 L( J2 Q8 |, M    #: of the IP address. *Type: dict*
1 ?: b' d+ V6 O( o0 o/ r    addresses = resource.Body('addresses', type=dict)8 y# e8 g6 K; M  R7 G# F+ ]: \+ `
    #: When a server is first created, it provides the administrator password.
8 S5 B3 a+ u! u- m    admin_password = resource.Body('adminPass')
" U( C) `/ m5 w- D' \" q    #: A list of an attached volumes. Each item in the list contains at least: ]) Q" z/ N! u/ b/ b
    #: an "id" key to identify the specific volumes.+ ^) e9 R- s5 M0 q2 k, s
    attached_volumes = resource.Body(
4 S9 V, N8 u& s! i8 x        'os-extended-volumes:volumes_attached')
0 b9 g+ U5 }. n1 i( {    #: The name of the availability zone this server is a part of.
1 l$ @, q2 _3 }: G3 @( t, w$ `( V    availability_zone = resource.Body('OS-EXT-AZ:availability_zone')
+ d5 @7 O0 M& L& m1 P    #: Enables fine grained control of the block device mapping for an
3 f. E0 @3 f/ Z( j1 o( i1 d: b7 h    #: instance. This is typically used for booting servers from volumes.
: e0 {: ?6 E7 e$ I* p* j3 |    block_device_mapping = resource.Body('block_device_mapping_v2')
) S8 w  i0 y. J% N0 J2 @; v0 x    #: Indicates whether or not a config drive was used for this server.
; p; B+ J1 ^, Z& _- g& k+ _    config_drive = resource.Body('config_drive')# d- {+ G: k' f0 O$ m+ F4 r
    #: The name of the compute host on which this instance is running.
7 y2 Q+ B7 g$ D7 ~. m    #: Appears in the response for administrative users only.6 v+ D- J2 M/ D% I, r; F1 n3 g* m
    compute_host = resource.Body('OS-EXT-SRV-ATTR:host')8 _: k! q/ H- d
    #: Timestamp of when the server was created.
0 \, |) O$ e  k; A( T9 l    created_at = resource.Body('created')
$ X  F: m. O" u: L& w% g; }( U    #: The description of the server. Before microversion* Y* n  q% S$ ]$ ?4 N
    #: 2.19 this was set to the server name.
/ R7 {# v- L- \; u    description = resource.Body('description')
" n1 M- g$ d2 p2 x" A" [+ t    #: The disk configuration. Either AUTO or MANUAL.
8 H0 _% S+ P$ y! D6 f; S2 x" B    disk_config = resource.Body('OS-DCF:diskConfig')
% ~; n" }4 y- X: g7 a    #: The flavor reference, as a ID or full URL, for the flavor to use for
( Q; ?6 n$ B: k, Y4 }& F, S7 M/ v    #: this server.
5 i3 [( C0 U: ?6 P6 k    flavor_id = resource.Body('flavorRef')
0 e  g# b  Q, n# l1 P9 |    #: The flavor property as returned from server.
. x  g3 J7 z. C8 ?    # TODO(gtema): replace with flavor.Flavor addressing flavor.original_name
( v( {. j) ~+ E! l1 S5 W" F: L    flavor = resource.Body('flavor', type=dict)
5 W) e+ @4 G. F# A& G    #: Indicates whether a configuration drive enables metadata injection.7 ^1 t6 y: X% E- ]* `& W* z/ A8 V
    #: Not all cloud providers enable this feature.
" @5 ?4 V6 ]/ x4 S    has_config_drive = resource.Body('config_drive')( J5 J: ~% A/ k! x8 [) G
    #: An ID representing the host of this server.
: N3 I: T% _2 B$ b5 ~3 ]: }    host_id = resource.Body('hostId')
4 K" C3 u& l/ N; a" t* p2 O* M4 y2 H    #: The host status.
+ f- f( v4 V$ @: v; d$ W    host_status = resource.Body('host_status')
  h. m/ b" F" A    #: The hostname set on the instance when it is booted.5 P( |5 H5 w1 ~8 x. i9 O. y
    #: By default, it appears in the response for administrative users only.: F1 b( R2 [$ \. v$ k& G$ O
    hostname = resource.Body('OS-EXT-SRV-ATTR:hostname')
8 q% Q) W$ T. ~/ [    #: The hypervisor host name. Appears in the response for administrative; `/ r% H" s2 n: B8 g% E7 _8 M* v
    #: users only.3 `' I5 B2 ]+ d: R& ^, {1 l
    hypervisor_hostname = resource.Body('OS-EXT-SRV-ATTR:hypervisor_hostname')
9 K3 Z( m3 H0 }3 ^    #: The image reference, as a ID or full URL, for the image to use for6 _3 ~0 |" ^3 l( X9 s: p
    #: this server.8 z! e  V7 C8 M2 g9 C* N
    image_id = resource.Body('imageRef')3 W3 _4 |: D* }* S; @
    #: The image property as returned from server.2 m  C' _! o. n- X: Q
    image = resource.Body('image', type=image.Image)) f: T3 h/ U4 k: x9 p3 J, ]% o/ f! R2 v! E
    #: The instance name. The Compute API generates the instance name from the
2 S2 e+ `9 p4 e7 J' t. ~. C    #: instance name template. Appears in the response for administrative users
9 Q3 l2 s# @5 T! o    #: only.
9 D" {1 k6 e' w2 w: P# l) ~  }    instance_name = resource.Body('OS-EXT-SRV-ATTR:instance_name')2 D" c! x. @% m" t1 G. ?; P  M( T( F
    # The locked status of the server
2 {6 G+ Q& u7 ?. ^  l. b4 K    is_locked = resource.Body('locked', type=bool)
1 A) W  Y2 [8 o  a* G4 h: k  I    #: The UUID of the kernel image when using an AMI. Will be null if not.
* W& C2 v  {. g! O2 k. v    #: By default, it appears in the response for administrative users only.
) d  p5 k1 W, V    kernel_id = resource.Body('OS-EXT-SRV-ATTR:kernel_id')
6 H+ w  G% i, e7 ?8 s* J1 c    #: The name of an associated keypair+ O- e) T5 V# w6 ~
    key_name = resource.Body('key_name')/ d1 k. Z: R, L
    #: When servers are launched via multiple create, this is the
# j; a" ~% }- r* M0 Z2 V1 f    #: sequence in which the servers were launched. By default, it
/ e1 Y; R; f7 L8 {6 U! F    #: appears in the response for administrative users only.( w/ y' L8 z, \6 s  d8 G. s
    launch_index = resource.Body('OS-EXT-SRV-ATTR:launch_index', type=int)# H. [* c2 _2 `5 x
    #: The timestamp when the server was launched.* h" Q- h+ @5 Y3 d/ [
    launched_at = resource.Body('OS-SRV-USG:launched_at')
$ g0 S/ Y* M/ c    #: Metadata stored for this server. *Type: dict*0 l, U% C6 ~2 ?8 I& ^
    metadata = resource.Body('metadata', type=dict)9 B: W# @" y1 [# ^
    #: A networks object. Required parameter when there are multiple
* b1 W' C/ d, A& r  ?    #: networks defined for the tenant. When you do not specify the+ C) J- |+ ^8 n9 M# H3 F
    #: networks parameter, the server attaches to the only network/ T) s2 f' @0 L: B: S5 u
    #: created for the current tenant.2 Z. A0 E  ]! q" ^8 Y/ S, a8 o
    networks = resource.Body('networks')
7 @5 B" _* L! n- q    #: The file path and contents, text only, to inject into the server at6 O' p, A& q7 ?/ e4 ~, s6 Y- v
    #: launch. The maximum size of the file path data is 255 bytes.
9 O( J* H$ k. Y  W' w- J! o# b    #: The maximum limit is The number of allowed bytes in the decoded,
9 b) b1 G5 t) M6 A# v3 ^9 U" T    #: rather than encoded, data.
2 ?% |1 U! C( d: ~4 E7 N1 ^% }    personality = resource.Body('personality')7 {& G( W' @/ Z! L4 u
    #: The power state of this server.7 c0 r" X1 E8 {' c
    power_state = resource.Body('OS-EXT-STS:power_state')
& O* a/ ^9 D7 T, s, x3 u2 z    #: While the server is building, this value represents the percentage* u/ F6 R4 v1 x5 R
    #: of completion. Once it is completed, it will be 100.  *Type: int*) h$ T" Q4 W: V# a
    progress = resource.Body('progress', type=int)
$ {* Y; ^3 r9 L5 Q    #: The ID of the project this server is associated with.0 C# x- J! Y+ }5 V! e( I5 F' ^
    project_id = resource.Body('tenant_id')5 D; }4 Q, M9 Z7 Z
    #: The UUID of the ramdisk image when using an AMI. Will be null if not.
  ^6 V/ b" t9 L) H0 T% M7 o: r    #: By default, it appears in the response for administrative users only.
( ?1 z- M- t7 ^) v    ramdisk_id = resource.Body('OS-EXT-SRV-ATTR:ramdisk_id')( e: N3 L1 `4 S4 A7 u
    #: The reservation id for the server. This is an id that can be
! ~# l9 E# k3 ~$ `: g, [* Y; k    #: useful in tracking groups of servers created with multiple create,! O% [1 `3 i0 f. ]
    #: that will all have the same reservation_id. By default, it appears
! ~- c- m" l4 k. {% Q. o+ K) }$ Z. P    #: in the response for administrative users only.
7 x$ }; W+ G/ F6 A    reservation_id = resource.Body('OS-EXT-SRV-ATTR:reservation_id')% _2 l, `& K) b- g4 u* I
    #: The root device name for the instance By default, it appears in the2 R7 ~: e& i2 O7 q
    #: response for administrative users only.
# F# @, ^# ]  f9 @- p    root_device_name = resource.Body('OS-EXT-SRV-ATTR:root_device_name')8 c+ |# a1 C& x0 i! S
    #: The dictionary of data to send to the scheduler.5 u6 ^, K) d* _- ~" O
    scheduler_hints = resource.Body('OS-SCH-HNT:scheduler_hints', type=dict)
( i# b5 \5 B' x: S7 Z    #: A list of applicable security groups. Each group contains keys for
' X% I$ k! |4 g% G' O% n9 y$ Q    #: description, name, id, and rules.- Q0 [' _7 j- c. l+ e% T: |
    security_groups = resource.Body('security_groups',; ^% _2 w! T$ g( j% r
                                    type=list, list_type=dict)! I# t+ U7 G5 ]* g& Q: Q% j
    #: The UUIDs of the server groups to which the server belongs., I+ ^, v9 Q+ @1 ~5 A: q4 s) r
    #: Currently this can contain at most one entry.
- v# r6 o! Y2 _    server_groups = resource.Body('server_groups', type=list, list_type=dict)
8 }( ]% ~8 F! r! {! w2 S    #: The state this server is in. Valid values include ``ACTIVE``,
0 N4 X+ C+ O& E) [+ @+ h# u* I    #: ``BUILDING``, ``DELETED``, ``ERROR``, ``HARD_REBOOT``, ``PASSWORD``,/ H, i' x1 G% G5 _  l1 K" k
    #: ``PAUSED``, ``REBOOT``, ``REBUILD``, ``RESCUED``, ``RESIZED``,
6 m' v/ r7 |3 ?    #: ``REVERT_RESIZE``, ``SHUTOFF``, ``SOFT_DELETED``, ``STOPPED``,
/ ~  b) ^4 }& Y( a: z; u) d    #: ``SUSPENDED``, ``UNKNOWN``, or ``VERIFY_RESIZE``.
& D! _: K) s5 w* r( z    status = resource.Body('status')
& J; v2 D( }, v/ }5 C! I    #: The task state of this server.
8 {$ X. M* q- r- b# z7 t$ u    task_state = resource.Body('OS-EXT-STS:task_state')
+ \) X7 E6 {& J- q$ X    #: The timestamp when the server was terminated (if it has been).
, U9 k# _: S2 S/ O    terminated_at = resource.Body('OS-SRV-USG:terminated_at')
0 \, O+ p3 D$ ]$ n1 i9 u    #: A list of trusted certificate IDs, that were used during image
% X2 |0 ?9 L" S% E    #: signature verification to verify the signing certificate./ L/ O* O+ |, }4 ~" `0 G; t% K
    trusted_image_certificates = resource.Body(- d+ C) [- d, D0 F  X, J2 u  U/ a: `
        'trusted_image_certificates', type=list)& B2 x: F& h, m3 V5 B( z7 q4 y: B
    #: Timestamp of when this server was last updated./ X4 P/ Q! k7 Y8 M! `5 h  i$ s
    updated_at = resource.Body('updated')1 D& M+ N4 g0 z5 F, M
    #: Configuration information or scripts to use upon launch.
2 M  R- b& T) r+ f, |0 Q    #: Must be Base64 encoded.! B  l# b* _( Q
    user_data = resource.Body('OS-EXT-SRV-ATTR:user_data')
" J3 `- b, g9 X' t0 W    #: The ID of the owners of this server.
- f, D' R+ B9 c% L( k" s, P    user_id = resource.Body('user_id')
* W, {6 T7 o2 w    #: The VM state of this server.. L! l; J, t2 d. T
    vm_state = resource.Body('OS-EXT-STS:vm_state')5 T# W; [! f1 H
    def _prepare_request(self, requires_id=True, prepend_key=True,+ A2 _- b* F1 H
                         base_path=None, **kwargs):
+ M; O1 ~+ Z3 X9 c/ w! k1 _        request = super(Server, self)._prepare_request(requires_id=requires_id,
+ M% g9 z# e% ~8 H6 F1 k                                                       prepend_key=prepend_key,5 K( o8 z  b, K6 j! e
                                                       base_path=base_path)# ]1 T0 W# O7 o9 v* h, f! x7 }
        server_body = request.body[self.resource_key]
% _9 W1 d; L8 S- g  C) T+ o9 q        # Some names exist without prefix on requests but with a prefix
# f2 `* y, O2 L9 z$ I        # on responses. If we find that we've populated one of these9 }! Y2 [' _* I1 ?
        # attributes with something and then go to make a request, swap out
6 g+ g$ N) G: T5 k        # the name to the bare version.1 O2 l4 z' l  L5 ~/ c+ Q
        # Availability Zones exist with a prefix on response, but not request) I8 I4 ?& v, J3 l; V
        az_key = "OS-EXT-AZ:availability_zone"
0 k& C% M( O, M: d        if az_key in server_body:
, {" o1 f2 C/ }' P' `8 z: U* ^- Q; q            server_body["availability_zone"] = server_body.pop(az_key)# q: Y' g; S; p% f$ u# [
        # User Data exists with a prefix on response, but not request
5 w+ p# o! O+ k! _; q4 ?        ud_key = "OS-EXT-SRV-ATTR:user_data"; E- ]2 O+ p" G/ d6 a
        if ud_key in server_body:; Z. H2 z' o9 r
            server_body["user_data"] = server_body.pop(ud_key)
- f" Q/ \5 U- E8 {+ ^) m        # Scheduler hints are sent in a top-level scope, not within the; ]2 `( Z  B7 y: `
        # resource_key scope like everything else. If we try to send
3 y" U( `- m) o0 w- I3 W% p        # scheduler_hints, pop them out of the resource_key scope and into0 q7 G# ]* |( q; v' h4 @3 k; G
        # their own top-level scope.
$ C4 f) R. o1 a& I6 V1 ^        hint_key = "OS-SCH-HNT:scheduler_hints"! Y" G$ ~1 x' l1 i4 q
        if hint_key in server_body:
/ q% [9 X* a3 K            request.body[hint_key] = server_body.pop(hint_key)
3 A- b3 v) C6 v8 E- t        return request; W. |- A$ s8 z! [2 `
    def _action(self, session, body, microversion=None):! i$ I+ t2 \8 [9 r$ M
        """Preform server actions given the message body."""
2 j! _' N. k" Y0 a; J7 K8 n9 U        # NOTE: This is using Server.base_path instead of self.base_path
4 J, m' d$ P/ m1 b        # as both Server and ServerDetail instances can be acted on, but; i, x) x! H. N0 g. |
        # the URL used is sans any additional /detail/ part." N# k; G1 R5 N! R# ?4 S
        url = utils.urljoin(Server.base_path, self.id, 'action')
& C# `: z. \7 O        headers = {'Accept': ''}
+ b* q1 V7 L8 x- Y2 S* O. \        response = session.post(
( S; U" l6 p& H9 T. \            url, json=body, headers=headers, microversion=microversion)
; M2 a) f2 L5 Z& h- c' i6 i# ?        exceptions.raise_from_response(response)
6 s& g/ s, ^6 C        return response
9 J) |% p- W+ O, r    def change_password(self, session, new_password):
2 K( x) b, R4 k8 G$ r) T3 Q3 C        """Change the administrator password to the given password."""% H  v6 _% {& g( C  Z5 [- K2 V+ W9 N
        body = {'changePassword': {'adminPass': new_password}}$ \5 k% q6 T. q0 _8 p1 M
        self._action(session, body)
4 F: K& K, h+ Z: k2 k    def get_password(self, session):  D: H6 F. c6 N6 u+ e2 X
        """Get the encrypted administrator password."""
! e7 Y+ j, I. O" p        url = utils.urljoin(Server.base_path, self.id, 'os-server-password')
2 P+ t) T7 m, Y& F% z        return session.get(url)/ r* M/ W3 a7 ]! Y# x) m- J
    def reboot(self, session, reboot_type):& G' T+ t' C- d8 `, e5 ]+ A, f- f
        """Reboot server where reboot_type might be 'SOFT' or 'HARD'."""
' e# X8 n5 e4 ?$ @5 Q1 B; e        body = {'reboot': {'type': reboot_type}}
+ Q3 D" u/ ^. L6 c" e) _        self._action(session, body)& @$ o$ ~" n. n( e: }  k5 W" I
    def force_delete(self, session):
5 l1 @# `/ N7 |, U+ t( o* M1 m& i2 e        """Force delete a server."""
: [6 S' W! }/ I5 z% q0 L  s        body = {'forceDelete': None}
( {7 B, O' V. S; D        self._action(session, body)
7 [$ \4 _# t; q2 ~( f    def rebuild(self, session, name, admin_password,
  n/ x0 q4 T5 i: G  f/ m) ]. Y$ i2 n                preserve_ephemeral=False, image=None,! u- q+ _: ~. h0 g. S; q
                access_ipv4=None, access_ipv6=None,
2 i+ s' ~3 o# c0 n" D                metadata=None, personality=None):) v! {) [# v7 R) {1 W1 N8 X' T
        """Rebuild the server with the given arguments."""
& H% W8 u# D, `- [  `        action = {
8 ~% I; Q: x; g1 c' s, w6 E' z+ b0 j            'name': name,: Q0 @, S5 A. h% S  s+ p
            'adminPass': admin_password,
0 l  I! z1 O' G7 s            'preserve_ephemeral': preserve_ephemeral
% @( l# h, k; U) ]        }. R& o- C" ^& y6 \1 J
        if image is not None:
/ N& E0 e1 W& t/ M  R            action['imageRef'] = resource.Resource._get_id(image)
8 g7 L4 N" b) ~        if access_ipv4 is not None:$ V- n' v0 s" p+ F4 f0 N
            action['accessIPv4'] = access_ipv4
3 K/ b# L# K3 h        if access_ipv6 is not None:
7 d  o8 P! T+ }0 |5 m            action['accessIPv6'] = access_ipv6
; a; v- ?: n# `6 T" _8 D        if metadata is not None:
4 r7 w+ R4 I  ~9 d, u6 Y. Z; Q( O            action['metadata'] = metadata' d6 Y# k9 G) H/ i! i. Y7 e' I
        if personality is not None:+ b* f3 C4 ?" H( X2 l
            action['personality'] = personality$ q. c7 X: d7 W- q2 D' a% L) ]
        body = {'rebuild': action}1 I0 f1 M3 o  n
        response = self._action(session, body)
: P' t7 ]9 Y7 m9 ~% `        self._translate_response(response)1 i  q$ i+ d  S4 |9 \  O) z+ }
        return self
+ M* E9 I$ ^& I9 X' t- h  d    def resize(self, session, flavor):
. H  d! P! N- K6 |& l& f        """Resize server to flavor reference."""1 k& z) e3 p5 q1 R8 |: K) \$ C- P
        body = {'resize': {'flavorRef': flavor}}5 |  a2 c; Q# c6 D
        self._action(session, body)
; t/ @4 j& o" L: h; ?% {: v    def confirm_resize(self, session):$ r2 Y# q8 M) P- K) y
        """Confirm the resize of the server."""
+ j) i- R: ]8 }) X1 {) q        body = {'confirmResize': None}
# ]6 V- [2 k8 H$ K& h6 a# i* p4 X        self._action(session, body)
8 @9 T" X5 E( K' g    def revert_resize(self, session):
, N( Q7 q- {' B- w6 d. Z; p0 s        """Revert the resize of the server."""3 F, t$ M% B1 ]( Y8 [
        body = {'revertResize': None}
' d$ x8 t3 }+ a0 f8 y        self._action(session, body)1 s0 @7 b. N* i/ C  Q- B  O6 x
    def create_image(self, session, name, metadata=None):
! a9 D3 r$ F: z0 _) F        """Create image from server."""9 c7 t: \2 J; @* I# R# H! E
        action = {'name': name}
+ N5 [* G  y6 x9 M. [. S        if metadata is not None:
; }7 U* G& ^5 X; j2 u) l4 q# q% e            action['metadata'] = metadata  P  P) G3 N; V
        body = {'createImage': action}
+ @% ^) ], P3 b        # You won't believe it - wait, who am I kidding - of course you will!0 e! O! h5 o( o8 ]  M8 K1 z  Q
        # Nova returns the URL of the image created in the Location
1 t: p; T; }  h8 {  _" \. }9 l5 Q, z        # header of the response. (what?) But, even better, the URL it responds
# x+ ?* S- V9 f' J( L$ @# t        # with has a very good chance of being wrong (it is built from
" u0 t, d8 t, [- u# _" D        # nova.conf values that point to internal API servers in any cloud, ?1 W. g2 G- l! C2 m2 N6 S8 \, X
        # large enough to have both public and internal endpoints.  v9 v/ V# U- t5 m) |/ R
        # However, nobody has ever noticed this because novaclient doesn't
/ Z, s5 Y) H) o; g  {* X        # actually use that URL - it extracts the id from the end of  {* ^6 i5 O# I
        # the url, then returns the id. This leads us to question:$ E2 c+ n. R) `0 Y, n# N- X6 K' B
        #   a) why Nova is going to return a value in a header
1 Y% {9 d" J% I; C6 @2 @# ^5 ^        #   b) why it's going to return data that probably broken1 b) j  f- G6 |- {* Y7 m
        #   c) indeed the very nature of the fabric of reality
" B& S. k( k' y! R  k. A) o: q        # Although it fills us with existential dread, we have no choice but
! e0 s! v2 X) m2 {$ a7 t        # to follow suit like a lemming being forced over a cliff by evil
( A( j$ [+ s$ T2 g        # producers from Disney.) e6 h) i* t4 _, W/ |! ^4 c! d
        microversion = None4 m/ G! s# n3 ?
        if utils.supports_microversion(session, '2.45'):
2 J' W( P. _5 e3 N3 _! p            microversion = '2.45'9 F" A8 N9 U/ p2 L7 w5 w
        response = self._action(session, body, microversion)
" N+ V" Y5 c1 \  `* L8 W        body = None8 K9 N2 r5 B3 v/ a9 X3 y, o
        try:
( w+ e, z0 r% i            # There might be body, might be not) L& }; j+ v0 d; [* ]
            body = response.json()" v, ]% {( F# Q" r" u# D
        except Exception:
/ K( X7 f$ J$ Z% @2 h+ _! i            pass$ }2 Z9 ]  N2 g+ a$ R/ c% k. o3 l
        if body and 'image_id' in body:
. C9 C9 z8 B' b            image_id = body['image_id']
. `& m( i! u4 q7 v% R) X! b        else:
# Q' I0 b9 C, y* \            image_id = response.headers['Location'].rsplit('/', 1)[1]) m$ |! l' H  @! n. S
        return image_id. v2 w$ ?& ~0 w8 `0 S4 z
    def add_security_group(self, session, security_group_name):
# }3 x4 K/ q! P" g        body = {"addSecurityGroup": {"name": security_group_name}}
% T" K2 p: ?, b: y( Y) k        self._action(session, body)  |) N  w1 \! d; ?& i4 N4 ]
    def remove_security_group(self, session, security_group_name):9 F8 q5 }: u0 q  r, H) M
        body = {"removeSecurityGroup": {"name": security_group_name}}, F- e3 |  m; Q: Y: B) f+ p
        self._action(session, body)' s4 _) [4 V5 I" i7 r# R' O  l# R
    def reset_state(self, session, state):
- t5 E& W( C1 m# B  ?        body = {"os-resetState": {"state": state}}
( t# Y8 l( z& l7 Q  L        self._action(session, body)
) i& k3 l% V- z4 `1 Y2 f    def add_fixed_ip(self, session, network_id):
1 w2 O* _! b! r        body = {"addFixedIp": {"networkId": network_id}}3 r$ K8 n9 r& P3 s+ m
        self._action(session, body)
* V3 v! B; {% e" x    def remove_fixed_ip(self, session, address):
  p2 w8 N! T, S, o        body = {"removeFixedIp": {"address": address}}8 j% _; x. H6 j* H* b/ g9 t4 ]
        self._action(session, body)
' D& V  H) |0 e7 a) ]; q# |, E    def add_floating_ip(self, session, address, fixed_address=None):
$ `; L$ l0 b. v- ?/ Q; ^1 w        body = {"addFloatingIp": {"address": address}}
. `7 E4 H/ ?0 K' c( o' z0 M        if fixed_address is not None:' T4 \- a) }: [$ `/ U
            body['addFloatingIp']['fixed_address'] = fixed_address- L  T5 g  h# t2 G* V5 C5 r
        self._action(session, body)
. G" X0 F$ O% A  O( b7 A    def remove_floating_ip(self, session, address):2 `: T& t5 R  {6 h* v3 d. K
        body = {"removeFloatingIp": {"address": address}}* B9 Z! L, z4 e. D5 s. Q' s
        self._action(session, body)/ y0 E: S8 U' e( a
    def backup(self, session, name, backup_type, rotation):9 s8 @# c2 M+ M+ F# U* S
        body = {
( X& N  n& b! V/ x4 o' |1 Q4 p/ c            "createBackup": {% U9 x  h! d, H3 R" x8 @) Q6 _6 _
                "name": name,
8 u$ i+ s+ |, w  U9 E- S, l                "backup_type": backup_type,
2 k, n8 F+ u2 o! n; V                "rotation": rotation. d& W' x0 }) N$ J7 C
            }- L+ x) \# |0 ^3 X3 U
        }! @, q. }: L1 h/ {  Y
        self._action(session, body)  E& r6 S3 }8 `8 K6 n
    def pause(self, session):, a, b5 Z; Z' p9 J  K! J! G1 ], V
        body = {"pause": None}
& A  x( h* y7 g" M: {        self._action(session, body)! X& D0 u2 j' q) R' ]' F* @
    def unpause(self, session):# q* \% O7 ]6 K  \7 d, o6 ?
        body = {"unpause": None}
" u/ C5 E' M/ p4 T! t        self._action(session, body)
. }/ k; r: E% ~% T) b5 _    def suspend(self, session):: T1 C4 g; J3 n0 g$ C
        body = {"suspend": None}
4 w4 }( [* c3 N! e' _+ |        self._action(session, body), }+ H' d) m8 O* ^: k
    def resume(self, session):
' y3 K& {/ {" I1 t2 f" u, Z" q        body = {"resume": None}# k8 G1 u! X) j) u
        self._action(session, body)( Q* U: \) y& b3 ]  {
    def lock(self, session):
% k5 Y7 b( w) C3 Y; X: c        body = {"lock": None}  }: d. h* q) W2 p! y2 l, J
        self._action(session, body)  {8 C1 _/ H2 {) G5 w/ G
    def unlock(self, session):
* s0 ?( j4 z( ], F) x9 A        body = {"unlock": None}
) I! h% O' q2 R  \8 Z" R" d0 L. ?' T# o        self._action(session, body)
2 T5 X( F6 h# i9 d- }    def rescue(self, session, admin_pass=None, image_ref=None):6 D. P" A$ D6 `+ ]0 U- j
        body = {"rescue": {}}* Z* R% O) P+ O6 @: s' w9 I
        if admin_pass is not None:' V6 F" Y1 l& ^
            body["rescue"]["adminPass"] = admin_pass
. z. |% ]  K( J' h0 m* S        if image_ref is not None:
1 ]2 V, N9 ?5 O6 t7 C, k( K2 d            body["rescue"]["rescue_image_ref"] = image_ref
8 _7 R. H" u* a, M9 r. Z; I1 J& P        self._action(session, body)
, E1 N" Z. X0 ~    def unrescue(self, session):
5 l) d6 z+ e9 S% _: F$ H) y7 Q        body = {"unrescue": None}: A2 m* g! L8 i& c- K; X
        self._action(session, body)/ s: D) }3 v0 e5 y% C$ c5 ~
    def evacuate(self, session, host=None, admin_pass=None, force=None):
) _! }6 @+ P6 G0 O        body = {"evacuate": {}}1 R4 I& X3 i8 O
        if host is not None:
2 n$ Q! E% A) G0 ~% U            body["evacuate"]["host"] = host- ?3 u7 B5 f6 j$ ?$ d
        if admin_pass is not None:
: F" H- ?' m( a6 b; k. r9 d            body["evacuate"]["adminPass"] = admin_pass& J! `! e* X8 b- `; u7 H
        if force is not None:
" @; k6 u( S' W            body["evacuate"]["force"] = force
% A! s5 }8 Q9 {% |        self._action(session, body)
# Z$ }2 t6 J! G0 j( Z/ C9 j) d2 X    def start(self, session):
. |1 O+ g* E. A3 N7 N. M0 Q        body = {"os-start": None}. [" Z8 {/ R# M) K; _5 T; D
        self._action(session, body)
+ L9 a" w2 v1 J" l) s    def stop(self, session):
' w6 Y9 z( l7 m6 O# g        body = {"os-stop": None}
. y2 h  `* l& }: _( o6 X4 B        self._action(session, body)
; J; q: q* I! |    def shelve(self, session):
' I( V3 _/ {4 ?$ u6 z8 a        body = {"shelve": None}
# e8 \, Y% t( H2 u2 u/ a- [        self._action(session, body)$ n$ U! s1 I8 P$ a( |
    def unshelve(self, session):
8 w  W* h& l4 {3 N" }$ m        body = {"unshelve": None}
6 A9 A- Q/ i) f) [/ ]# z- }! W+ F% b& A  S        self._action(session, body)+ j; J0 U! o2 Z0 R% v
    def migrate(self, session):$ I3 V( M7 r  E5 b, Q: D
        body = {"migrate": None}+ Y" x8 {8 `7 ~& W6 U
        self._action(session, body)# t1 {/ |' o7 ^  @
    def get_console_output(self, session, length=None):& O9 F  a* p; B, o- S
        body = {"os-getConsoleOutput": {}}
) x  Y( J& q- [0 m        if length is not None:
5 C1 {5 |3 V$ ], X) z6 o1 ]            body["os-getConsoleOutput"]["length"] = length
' b( K- y$ k  Y/ H: w7 x+ ]4 e5 l        resp = self._action(session, body)
9 B/ z6 _& |2 ~        return resp.json()9 K% d* n7 R3 B0 \) L
    def get_console_url(self, session, console_type):
) P0 E& q  ?0 O$ Y$ @        action = CONSOLE_TYPE_ACTION_MAPPING.get(console_type)9 G; V4 ]% ^  [/ v. {0 Z, H4 ^
        if not action:
& |* `+ e& z1 c            raise ValueError("Unsupported console type %s" % console_type)
/ l  k6 {" N9 c6 h        body = {action: {'type': console_type}}+ I6 {0 Y1 B, N, n7 D9 I8 |
        resp = self._action(session, body)- L. _$ j! o2 ?3 X' T1 I' A
        return resp.json().get('console')
* `+ v' p. G. I( q    def live_migrate(self, session, host, force, block_migration,, P7 c: Q: m1 m- P8 u. j+ j# ]. x7 g
                     disk_over_commit=False):3 L" L% g. b; Q/ O$ q* {6 M9 \
        if utils.supports_microversion(session, '2.30'):0 y0 }7 ?; m& h. D) }2 M. C
            return self._live_migrate_30(/ j5 _; Y, D' u6 O2 E) u
                session, host,, E2 y: j; {* H# B! [. w
                force=force,
* L( v9 n, C3 s6 \                block_migration=block_migration), \- F$ e  g: _
        elif utils.supports_microversion(session, '2.25'):- O# ?: e2 c# _" w; u  M- _
            return self._live_migrate_25($ V) K3 h6 k. c' u
                session, host,
7 m4 W  y1 {3 j                force=force,# n3 x& G% J& n. C; L3 l" ~8 N6 x
                block_migration=block_migration), w9 K/ r4 m* ]$ g
        else:: y2 \2 X# j+ y  B9 E
            return self._live_migrate(
- r3 e1 K, ?7 ~: c" [# t8 f0 `                session, host,; h% p( {* J# v0 B# Y) g( M
                force=force,( ~) N. y% d8 R. Z, z1 C7 h8 E
                block_migration=block_migration,$ ^; T. K. [+ C8 p4 M2 |
                disk_over_commit=disk_over_commit); F) H; H  t7 a; X/ k( b8 K' b8 b
    def _live_migrate_30(self, session, host, force, block_migration):
0 y  o4 {' G  k" n+ c3 e        microversion = '2.30'/ b, n6 w) S9 ?. \$ D6 K8 P
        body = {'host': None}
: {. l# C9 q2 n        if block_migration is None:
3 H/ Q7 o; @' t" Y            block_migration = 'auto'
' Z9 p4 @' d: s1 Z4 c        body['block_migration'] = block_migration
0 L, ]5 j- R) S        if host:
& w, F3 k0 r! T% f$ w            body['host'] = host
5 N. N8 P3 f! C) v' c2 M            if force:
" ?8 m& ?( u8 T' |5 i8 Z                body['force'] = force
9 C; a& c3 N1 [6 Z/ C' S        self._action(
' h; y5 ~' y# L            session, {'os-migrateLive': body}, microversion=microversion)
- n4 u  A: d0 f# t" @) t, m' f% K    def _live_migrate_25(self, session, host, force, block_migration):) x, @- T* f. G
        microversion = '2.25'
& W, P. |& S* o8 L" \6 f& p        body = {'host': None}
" @0 W, I& e+ u: W+ I* v        if block_migration is None:- u6 F" |: F! `
            block_migration = 'auto'+ X# y% r. o: D
        body['block_migration'] = block_migration
$ F. r, e# g' U4 y        if host:; d# q, d" }: o/ a0 k
            body['host'] = host! k6 u2 d& B% A, Q% F' S
            if not force:% _/ z$ ?7 r" V! W
                raise ValueError(! L1 h; ^. X0 A# x" C4 E# n2 i6 Y
                    "Live migration on this cloud implies 'force'"/ t! [8 l- `% Y
                    " if the 'host' option has been given and it is not"
( v9 c4 U8 z9 g3 O. |& q                    " possible to disable. It is recommended to not use 'host'"# G$ r5 Z$ Z/ Z
                    " at all on this cloud as it is inherently unsafe, but if", q! d# A; N, j# r& G4 {7 ~
                    " it is unavoidable, please supply 'force=True' so that it"
; z* P5 a# a1 U' W- O& N                    " is clear you understand the risks.")
; ?% T, w  k: T$ w        self._action(
# y& R+ G6 R( x% c3 B/ H            session, {'os-migrateLive': body}, microversion=microversion)
8 k- F8 @8 A# c8 O: J$ Z# j' E    def _live_migrate(self, session, host, force, block_migration,. U8 j2 [: g8 E- b
                      disk_over_commit):  @, D$ N, V( {) `! l
        microversion = None/ g: H) t; C* c, H/ j
        body = {
# v1 R/ `) [6 E9 [            'host': None,/ e6 ^% P5 x4 P9 `, ]
        }/ j7 p6 H  M& ~' R
        if block_migration == 'auto':9 F) P3 Y( ~5 q4 Q& X+ C
            raise ValueError() e+ r7 \$ i0 w  m
                "Live migration on this cloud does not support 'auto' as"
: @" M1 N/ \% u+ `7 F2 D" F5 M' O                " a parameter to block_migration, but only True and False."); `$ j9 [6 b9 q3 G1 @% A* |- d
        body['block_migration'] = block_migration or False, ^( Q) C, |  k8 j$ l# a/ v/ ~
        body['disk_over_commit'] = disk_over_commit or False9 ~9 p+ B; a7 B: \7 [3 e# Q% K
        if host:
* W0 [+ h& t1 z. F( E) r8 J            body['host'] = host
! O1 i2 C% L* X            if not force:% J+ l5 `7 |+ k' U! V
                raise ValueError(
) M! T6 Q( Y5 [8 q$ N5 W, R                    "Live migration on this cloud implies 'force'"
, b4 ]3 y# U- f- Z" Z' t                    " if the 'host' option has been given and it is not"
- ]2 [$ d- _# t' z                    " possible to disable. It is recommended to not use 'host'"
2 p% E8 x3 W* W% ~$ W                    " at all on this cloud as it is inherently unsafe, but if") e; h3 t- Q$ ~0 e- `: ~
                    " it is unavoidable, please supply 'force=True' so that it"5 M; n* X4 M- T, R
                    " is clear you understand the risks.")
- S- V  n$ U& k% _$ [3 p        self._action(- N8 D' [1 |1 q+ R3 s. i
            session, {'os-migrateLive': body}, microversion=microversion)
$ B$ S6 Y  l% b- E: i    def fetch_security_groups(self, session):8 P3 s# v$ X, X& w9 q3 B" h
        """Fetch security groups of a server.* D  {4 `: p! j, Q
        :returns: Updated Server instance.
# P0 v0 I) e' z. `0 ?! ~        """" ]( n/ @5 ~7 ?% z
        url = utils.urljoin(Server.base_path, self.id, 'os-security-groups')6 A4 m: C5 P  ?; m1 ?8 c
        response = session.get(url), E: s9 S+ `0 ^8 J; W
        exceptions.raise_from_response(response)/ P' L8 E( @3 W
        try:
/ ?4 c9 g8 F, W! j& q# }* E" Y- y% y# F            data = response.json()7 A7 Q1 {, H- ~0 b2 o! ?( @
            if 'security_groups' in data:
9 h- t2 R4 Q5 b) T4 \                self.security_groups = data['security_groups']
$ e& o5 R: A1 y3 x  H        except ValueError:
. q" B: E* G* b% B            pass, Y/ ]+ W0 X  J& R9 U- j( u
        return self
3 F( s3 f6 S. b5 O8 I  P& v
8 |9 r$ T7 V6 c. h2 a, cServerDetail = Server
6 s# o6 q9 P! ~% y, G( ^- J- y0 u4 p2 H

4 x% Q$ n& P; _  {8 B* _- ?

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-9-3 15:49:26 | 显示全部楼层

$ Z, B& p& }8 v' ^7 f2 g0 [1 O4 w' q- L) b
* S, L$ M; T% O# e" N4 t/ ~
2 p; l$ c% J$ F) R9 b. ]
源码
, d/ \6 y# m9 A- G/ d8 j9 h4 ^

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-9-3 15:52:54 | 显示全部楼层
ansible task
. k! s$ ^9 V' L" `* N/ M" O7 W, [, kansible-playbook xxxx.yml1 [# r; V, U: K
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 02:22 , Processed in 0.033671 second(s), 29 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表