1
+ from time import sleep
2
+
3
+ from unicon .plugins .iosxe .connection_provider import IosxeSingleRpConnectionProvider
4
+
5
+
6
+ class VpagentSingleRpConnectionProvider (IosxeSingleRpConnectionProvider ):
7
+ """ Implements Vpagent singleRP Connection Provider,
8
+ This class overrides the base class with the
9
+ additional dialogs and steps required for
10
+ connecting to any device via generic implementation
11
+ """
12
+
13
+ def __init__ (self , * args , ** kwargs ):
14
+
15
+ """ Initializes the generic connection provider
16
+ """
17
+ super ().__init__ (* args , ** kwargs )
18
+
19
+
20
+ def establish_connection (self ):
21
+ """ Reads the device state and brings it to the right state
22
+ Note: Passive hostname learning is enabled by default and will
23
+ give a warning if the device hostname does not match the learned
24
+ hostname. The learned hostname is only used if user specifies
25
+ `learn_hostname=True`. A timeout may occur if the prompt pattern
26
+ uses the hostname, the timeout error includes the hostname and
27
+ a hint to check the hostname if a mismatch was detected.
28
+ """
29
+ con = self .connection
30
+
31
+ # Enable hostname learning by default
32
+ con .state_machine .learn_hostname = True
33
+ con .state_machine .learn_pattern = con .settings .DEFAULT_LEARNED_HOSTNAME
34
+
35
+ context = self .connection .context
36
+ if (login_creds := context .get ('login_creds' )):
37
+ context .update (cred_list = login_creds )
38
+
39
+ # Before accessing the vm since device is not ready and connection may be
40
+ # closed by vcenter manger we need to wait before accessing the device.
41
+ timeout = con .settings .WAITE_TIMEOUT
42
+ con .log .info (f'sleeping for { timeout } seconds before accessing the device!' )
43
+ sleep (timeout )
44
+
45
+ dialog = self .get_connection_dialog ()
46
+ # Try to bring device to any state connection may be closed during bring the device
47
+ # to a valid and cause an IO error
48
+ output = self ._get_device_to_any (con , context , dialog )
49
+ # if device is still in generic state that means we could not bring device to any state and
50
+ # spawn is closed so we need to create a new spawn and try again to bring device to any state
51
+ if con .state_machine .current_state == 'generic' :
52
+ con .setup_connection ()
53
+ output = self ._get_device_to_any (con , context , dialog )
54
+
55
+ if con .state_machine .current_state == "config" :
56
+ con .state_machine .go_to ('enable' ,
57
+ self .connection .spawn ,
58
+ context = context ,
59
+ prompt_recovery = self .prompt_recovery ,
60
+ timeout = self .connection .connection_timeout )
61
+
62
+ if con .state_machine .current_state not in ['rommon' , 'standby_locked' , 'shell' ]:
63
+ cur_state = con .state_machine .get_state (con .state_machine .current_state )
64
+ # if the learn hostname is set to True the pattern for state machine updated with
65
+ # '(?P<hostname00...)' regex patterns so we check for the pattern before learning the hostname
66
+ if 'P<hostname' in cur_state .pattern :
67
+ self .learn_hostname ()
68
+ # If device is found in one of the above states, init_handle()
69
+ # will change the device state to enable, after which
70
+ # hostname learning and token discovery is done.
71
+ self .learn_tokens ()
72
+
73
+ con .state_machine .learn_hostname = False
74
+ context .pop ('cred_list' , None )
75
+
76
+ return output
77
+
78
+ def _get_device_to_any (self , connection , context , dialog ):
79
+ try :
80
+ connection .state_machine .go_to ('any' ,
81
+ self .connection .spawn ,
82
+ context = context ,
83
+ prompt_recovery = self .prompt_recovery ,
84
+ timeout = self .connection .connection_timeout ,
85
+ dialog = dialog )
86
+ except Exception :
87
+ connection .setup_connection ()
88
+ self ._get_device_to_any (connection , context , dialog )
0 commit comments