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

openstack使用ansible nova配置

[复制链接]

1

主题

0

回帖

12

积分

管理员

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

9 n4 s0 f# {! J/ l  D

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-9-3 15:49:26 | 显示全部楼层
8 p- f5 ^* E6 o( d5 O/ r
5 H( q/ M9 B1 c& G6 M

3 B9 M2 t$ R1 E% O) M# ?: n6 r) a( Q) t# H
, c, @# P4 _3 Q1 u) Y# e源码
; ~  Z1 j" V2 l( @+ w& ?3 a% \

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-9-3 15:52:54 | 显示全部楼层
ansible task
. ]8 c. Y3 Z; Z; V# cansible-playbook xxxx.yml. c% F. l' I+ l# @# c" c
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 04:26 , Processed in 0.032311 second(s), 29 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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