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

openstack使用ansible nova配置

[复制链接]

1

主题

0

回帖

12

积分

管理员

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

! Y3 O4 e6 v# b7 OServerDetail = Server
2 K, z  B& V* n2 U9 k
; K( w" X- ^1 n  x' E& ~$ _, y% R( ~5 E1 C! ~0 d4 d8 I( e

1

主题

0

回帖

12

积分

管理员

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

, L# n+ \6 Y) y" @3 _5 I5 E
5 |7 Y5 A$ b) S4 }5 a, W: L: j4 N

1 A! L8 n6 i( R源码
2 _5 A' P# A/ n% G; }

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-9-3 15:52:54 | 显示全部楼层
ansible task
3 a! h/ x. E2 X) w  F. @ansible-playbook xxxx.yml0 {+ _2 x3 H$ e: F
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 02:18 , Processed in 0.041202 second(s), 28 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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