2424 """
2525 sys .exit (0 )
2626
27- # driver.get(SITE1_URL)
28- # driver.find_element_by_tag_name('body').send_keys(Keys.COMMAND + 't')
29- # driver.get(SITE2_URL)
30- # driver.find_element_by_tag_name('body').send_keys(Keys.COMMAND + 't')
31-
3227class TestBasicExport (unittest .TestCase ):
28+ @staticmethod
29+ def _start_server (db_filename , server_port ):
30+ os .environ ["MULTISITE_DATABASE_FILE" ] = db_filename
31+ subprocess .call (["rm" , "-rf" , db_filename ])
32+ subprocess .Popen (["python" , "multisite-gui.py" , "--port" , server_port , "--test" ])
33+ time .sleep (1 )
34+
3335 @classmethod
3436 def setUpClass (cls ):
35-
36-
3737 # Run the multisite tool for first site
38- site1_db_filename = "site1_db.sqlite"
39- os .environ ["MULTISITE_DATABASE_FILE" ] = site1_db_filename
40- subprocess .call (["rm" , "-rf" , site1_db_filename ])
41- subprocess .Popen (["python" , "multisite-gui.py" , "--port" , "5000" , "--test" ])
42- time .sleep (1 )
38+ cls ._start_server ('site1_db.sqlite' , '5000' )
4339
4440 # Run the multisite tool for second site
45- site2_db_filename = "site2_db.sqlite"
46- os .environ ["MULTISITE_DATABASE_FILE" ] = site2_db_filename
47- subprocess .call (["rm" , "-rf" , site2_db_filename ])
48- subprocess .Popen (["python" , "multisite-gui.py" , "--port" , "5001" , "--test" ])
49- time .sleep (1 )
41+ cls ._start_server ('site2_db.sqlite' , '5001' )
5042
43+ # Start the browser
5144 cls .driver = webdriver .Firefox ()
5245
46+ def _enter_credentials (self , driver , site_name , ip_address , user_name , password , local ):
47+ # Enter the Site 1 credentials
48+ typing = [('site_name' , site_name ),
49+ ('ip_address' , ip_address ),
50+ ('user_name' , user_name ),
51+ ('password' , password )]
52+ for (field , data ) in typing :
53+ input_elem = driver .find_element_by_id (field )
54+ input_elem .send_keys (data )
55+ if local :
56+ input_elem = driver .find_element_by_id ('local' )
57+ input_elem .click ()
58+
59+ def _login_session (self , url , login , password ):
60+ session = Session (url , login , password )
61+ resp = session .login ()
62+ self .assertTrue (resp .ok )
63+ return session
64+
65+
5366 def setup_site (self , url , site1_local = True ):
54- # driver = webdriver.Firefox()
55- # driver.maximize_window()
5667 driver = self .__class__ .driver
5768 driver .find_element_by_tag_name ('body' ).send_keys (Keys .COMMAND + 't' )
5869
@@ -65,32 +76,16 @@ def setup_site(self, url, site1_local=True):
6576 driver .find_element_by_link_text ('Create' ).click ()
6677
6778 # Enter the Site 1 credentials
68- typing = [('site_name' , 'Site1' ),
69- ('ip_address' , SITE1_IP ),
70- ('user_name' , SITE1_LOGIN ),
71- ('password' , SITE1_PASSWORD )]
72- for (field , data ) in typing :
73- input_elem = driver .find_element_by_id (field )
74- input_elem .send_keys (data )
75- if site1_local :
76- input_elem = driver .find_element_by_id ('local' )
77- input_elem .click ()
79+ self ._enter_credentials (driver , 'Site1' , SITE1_IP , SITE1_LOGIN ,
80+ SITE1_PASSWORD , site1_local )
7881
7982 # Save the credentials
8083 input_elem = driver .find_element_by_name ('_add_another' )
8184 input_elem .click ()
8285
8386 # Enter the Site 2 credentials
84- typing = [('site_name' , 'Site2' ),
85- ('ip_address' , SITE2_IP ),
86- ('user_name' , SITE2_LOGIN ),
87- ('password' , SITE2_PASSWORD )]
88- for (field , data ) in typing :
89- input_elem = driver .find_element_by_id (field )
90- input_elem .send_keys (data )
91- if not site1_local :
92- input_elem = driver .find_element_by_id ('local' )
93- input_elem .click ()
87+ self ._enter_credentials (driver , 'Site2' , SITE2_IP , SITE2_LOGIN ,
88+ SITE2_PASSWORD , not site1_local )
9489
9590 # Save the credentials
9691 input_elem = driver .find_element_by_name ('_add_another' )
@@ -102,12 +97,35 @@ def setup_site(self, url, site1_local=True):
10297
10398 # TODO: go to the site screen and verify that both sites are present
10499
100+ def _verify_l3extsubnet (self , session , tenant_name , mac , ip , present = True ):
101+ class_query_url = ("/api/mo/uni/tn-%s.json?query-target=subtree&"
102+ "target-subtree-class=l3extSubnet" % tenant_name )
103+ resp = session .get (class_query_url )
104+ data = resp .json ()['imdata' ]
105+ if present :
106+ self .assertTrue (len (data ))
107+ found = False
108+ for subnet in data :
109+ self .assertTrue ('l3extSubnet' in subnet )
110+ dn = subnet ['l3extSubnet' ]['attributes' ]['dn' ]
111+ if mac in dn and ip in dn :
112+ found = True
113+ if present :
114+ self .assertTrue (found )
115+ else :
116+ self .assertFalse (found )
117+
118+
105119 def test_01_site1 (self ):
106120 self .setup_site ('http://127.0.0.1:5000' , site1_local = True )
107121
108122 def test_02_site2 (self ):
109123 self .setup_site ('http://127.0.0.1:5001' , site1_local = False )
110124
125+ # TODO test removing a site
126+ # TODO test adding the same site twice
127+ # TODO
128+
111129 def test_03_export_contract (self ):
112130 driver = self .__class__ .driver
113131 # Switch to the site 1 tool
@@ -135,18 +153,14 @@ def test_03_export_contract(self):
135153
136154 time .sleep (1 )
137155 # Verify that the export to the other APIC was successful
138- session = Session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
139- resp = session .login ()
140- self .assertTrue (resp .ok )
156+ session = self ._login_session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
141157 tenants = Tenant .get_deep (session , names = ['multisite' ], limit_to = ['fvTenant' , 'vzBrCP' ])
142158 self .assertTrue (len (tenants ) > 0 )
143159 multisite_tenant = tenants [0 ]
144160 self .assertIsNotNone (multisite_tenant .get_child (Contract , 'Site1:mysql-contract' ))
145161
146162 def test_04_consume_exported_contract (self ):
147- session = Session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
148- resp = session .login ()
149- self .assertTrue (resp .ok )
163+ session = self ._login_session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
150164
151165 # Create the Tenant
152166 tenant = Tenant ('multisite' )
@@ -172,9 +186,7 @@ def test_04_consume_exported_contract(self):
172186 self .assertTrue (epg .does_consume (contract ))
173187
174188 def test_05_add_consuming_static_endpoint (self ):
175- session = Session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
176- resp = session .login ()
177- self .assertTrue (resp .ok )
189+ session = self ._login_session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
178190
179191 tenant = Tenant ('multisite' )
180192 app = AppProfile ('my-demo-app' , tenant )
@@ -207,10 +219,15 @@ def test_05_add_consuming_static_endpoint(self):
207219 ep = epg .get_child (Endpoint , '00:33:33:33:33:33' )
208220 self .assertIsNotNone (ep )
209221
222+ session = self ._login_session (SITE1_URL , SITE1_LOGIN , SITE1_PASSWORD )
223+ self ._verify_l3extsubnet (session ,
224+ tenant_name = 'multisite' ,
225+ mac = '00:33:33:33:33:33' ,
226+ ip = '2.3.4.5/32' ,
227+ present = True )
228+
210229 def test_06_add_providing_static_endpoint (self ):
211- session = Session (SITE1_URL , SITE1_LOGIN , SITE1_PASSWORD )
212- resp = session .login ()
213- self .assertTrue (resp .ok )
230+ session = self ._login_session (SITE1_URL , SITE1_LOGIN , SITE1_PASSWORD )
214231
215232 tenant = Tenant ('multisite' )
216233 app = AppProfile ('my-demo-app' , tenant )
@@ -246,6 +263,60 @@ def test_06_add_providing_static_endpoint(self):
246263 ep = epg .get_child (Endpoint , '00:44:44:44:44:44' )
247264 self .assertIsNotNone (ep )
248265
266+ session = self ._login_session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
267+ self ._verify_l3extsubnet (session ,
268+ tenant_name = 'multisite' ,
269+ mac = '00:44:44:44:44:44' ,
270+ ip = '7.8.9.10/32' ,
271+ present = True )
272+
273+ def test_07_remove_consuming_static_endpoint (self ):
274+ session = self ._login_session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
275+
276+ tenant = Tenant ('multisite' )
277+ app = AppProfile ('my-demo-app' , tenant )
278+ web_epg = EPG ('web-frontend' , app )
279+
280+ # Create the Endpoint
281+ ep = Endpoint ('00:33:33:33:33:33' , web_epg )
282+ ep .mac = '00:33:33:33:33:33'
283+ ep .ip = '2.3.4.5'
284+
285+ intf = Interface ('eth' , '1' , '101' , '1' , '38' )
286+ # Create a VLAN interface and attach to the physical interface
287+ vlan_intf = L2Interface ('vlan-5' , 'vlan' , '5' )
288+ vlan_intf .attach (intf )
289+ # Attach the EPG to the VLAN interface
290+ web_epg .attach (vlan_intf )
291+ # Assign Endpoint to the L2Interface
292+ ep .attach (vlan_intf )
293+
294+ # Mark the Endpoint as deleted
295+ ep .mark_as_deleted ()
296+
297+ print 'Pushing json to tenant' , tenant .get_json ()
298+ resp = tenant .push_to_apic (session )
299+ self .assertTrue (resp .ok )
300+
301+ # Verify that the Endpoint has been removed
302+ time .sleep (1 )
303+ tenants = Tenant .get_deep (session , names = ['multisite' ])
304+ multisite_tenant = tenants [0 ]
305+ app = multisite_tenant .get_child (AppProfile , 'my-demo-app' )
306+ self .assertIsNotNone (app )
307+ epg = app .get_child (EPG , 'web-frontend' )
308+ self .assertIsNotNone (epg )
309+ ep = epg .get_child (Endpoint , '00:33:33:33:33:33' )
310+ self .assertIsNone (ep )
311+
312+ # Verify that the l3extSubnet has been removed from the other site
313+ session = self ._login_session (SITE2_URL , SITE2_LOGIN , SITE2_PASSWORD )
314+ self ._verify_l3extsubnet (session ,
315+ tenant_name = 'multisite' ,
316+ mac = '00:33:33:33:33:33' ,
317+ ip = '2.3.4.5/32' ,
318+ present = False )
319+
249320 @classmethod
250321 def tearDownClass (cls ):
251322 driver = cls .driver
0 commit comments